고랭지농업

크롤러 만들기 [5] - 최적화 및 JSON 으로 반환하기

이번 편이 최적화 편이지만 아무래도 고수분들이 보시기엔 어? 이게 최적화?? 라고 의문을 가질 수도 있습니다... 저는 개초보이기때문에... 더 좋은 아이디어가 있다면 말씀해주세요.

 

 

4편에서 썼던 소스코드는 약 28초~30초가 걸립니다.

왜냐면 /app/controllers/crawl_controllers.go 에서

[code]

...

subjectResult, err := contentCrawl(client, urlResult, reg["subject"])

...

contentResult, err := contentCrawl(client, urlResult, reg["content"])

...

[/code]

 

코드가 있는데 이때 제목 파싱을 하기위해 웹 페이지 소스코드를 한번 쭉 읽고, 본문 파싱을 하기 위해 웹 페이지 코드를 다시 쭉 읽습니다.

고로 2배의 시간이 더 걸리네요.

이것을 하나로 합치고, 합치는 김에 JSON을 반환할 수 있도록 합시다.

 

/app/controlles/crawl_controller.go

[code]

...

func crawl(url string, reg map[string]string) (map[string]map[string]string, error) {

    var err error

    client := resty.New()

    urlResult := make([]string, 0)

    result := make(map[string]map[string]string, 0)

 

    url = strings.Split(url, ":page:")[0])

    if reg["url"] != "" {

        urlResult, err = boardCrawl(client, url, reg["url"])

        if err != nil {

            return result, err

        }

    }

   

    if reg["subject"] != "" && reg["content"] != "" {

        result, err = contentCrawl(client, urlResult, reg)

        if err != nil {

            return result, err

        }

    }

 

    return result, err

}

...

func contentCrawl(client *resty.Client, url []string, reg map[string]string) (map[string]map[string]string, error) {

    contentResult := make(map[string]map[string]string)

 

    for i := 0; i < len(url); i++ {

        contentResult[url[i]] = make(map[string]string)

        resp, err := client.R().Get(url[i])

        if err != nil {

            return contentResult, err

        }

       

        regSubject, err := regexp.Complie(`(?m)` + regex["subject"])

        if err != nil {

            return contentResult, err

        }

 

        subject := regSubject.FindStringSubmatch(resp.String())

        if len(subject) == 0 {

            delete(contentResult, url[i])

            continue

        }

 

        regContent, err := regexp.Complie(`(?m)` + regex["content"])

        if err != nil {

            return contentResult, err

        }

 

        content := regContent.FindStringSubmatch(resp.String())

        if len(content) == 0 {

            delete(contentResult, url[i])

            continue

        }

 

        contentResult[url[i]][subject[1]] = content[1]

    }

    return contentResult, nil

}

[/code]

 

수정한 코드는 이제 아래와 같은 역할을 합니다.

제목과 본문 파싱은 한번에 수행합니다.

수집한 결과값은 아래와 같이 저장됩니다.

["링크"]["제목"] -> "본문"

 

 이제 이를 JSON 형태로 변환해봅시다.

 

/app/models/crawl_model.go

[code]

package models

 

type Data struct {

    Content []Content `json:"content"`

}

 

type Content struct {

    URL       string    `json:"url"`

    Title       string    `json:"title"`

    Content  string    `json:"content"`

}

[/code]

 

이제 이 구조체를 이용해 반환된 값을 JSON 형태로 바꿀 수 있습니다.

 

/app/controllers/web_controller.go

[code]

....

func Crawl(c *fiber.Ctx) error {

    url := c.FormValue("url")

    reg := make(map[string]string)

    reg["url"] = c.FormValue("regex_url")

    reg["subject"] = c.FormValue("regex_subject")

    reg["content"] = c.FormValue("regex_content")

 

    result, err := crawl(url, reg)

    if err != nil {

        return c.SendString(err.Error())

    }

 

    content := make([]models.Content, 0)

   

    for k, v := range result {

        for k1, v1 := range v {

            content = append(content, models.Content{

                URL: k,

                Title: k1,

                Content: v1,

            }

        }

    }

   

    return c.JSON(models.Data{

        Content: content,

    })

}

[/code]

 

1030332716_1677850778.9088.png

 

비밀글 및 정규표현식으로는 제목과 본문을 읽을 수 없는 경우를 제외하고

약 186개의 게시물을 읽고 JSON으로 반환하는데 까지 걸리는 시간은 아래와 같습니다.

 

1030332716_1677850830.0532.png

 

이 시간은 제 컴퓨터에서 대상 사이트에 접근하는 시간 + 수집하는 시간 + JSON으로 변환하는 시간 등등 모든 시간이 다 포함된 시간입니다.

 

이걸로 마무리가 되었네요.

 

아무래도 주석 한줄 없다보니 많은 사람들이 읽기 엄청 어려우셨을 겁니다...

그래도 여기까지 와주셔서 감사합니다.

 

질문이 있으시면 언제든지 답해드리겠습니다.

|

댓글 1개

지금 다시보니 코드가 정말 개판이네요....
댓글을 작성하시려면 로그인이 필요합니다.

Golang

+
제목 글쓴이 날짜 조회
2년 전 조회 529
2년 전 조회 1,203
2년 전 조회 557
2년 전 조회 775
2년 전 조회 619
3년 전 조회 930
3년 전 조회 599
3년 전 조회 648
3년 전 조회 651
3년 전 조회 925
3년 전 조회 1,078
3년 전 조회 646
3년 전 조회 928
4년 전 조회 973
4년 전 조회 1,128
4년 전 조회 1,042
4년 전 조회 1,631
4년 전 조회 1,364
4년 전 조회 1,185
4년 전 조회 1,263
4년 전 조회 1,264
4년 전 조회 1,212
4년 전 조회 1,218
4년 전 조회 1,868
5년 전 조회 1,295
6년 전 조회 2,313
6년 전 조회 1,686
6년 전 조회 1,251
6년 전 조회 1,457
6년 전 조회 1,299