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

매출이 오르면 내리는 수수료! 지금 수수료센터에서 전자결제(PG)수수료 비교견적 신청해 보세요!

Golang

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

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

본문

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

 

 

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

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


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

 

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

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

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

 

/app/controlles/crawl_controller.go


...
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
}

 

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

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

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

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

 

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

 

/app/models/crawl_model.go


package models
 
type Data struct {
    Content []Content `json:"content"`
}
 
type Content struct {
    URL       string    `json:"url"`
    Title       string    `json:"title"`
    Content  string    `json:"content"`
}

 

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

 

/app/controllers/web_controller.go


....
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,
    })
}

 

1030332716_1677850778.9088.png

 

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

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

 

1030332716_1677850830.0532.png

 

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

 

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

 

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

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

 

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

추천
1

댓글 1개

전체 40 |RSS
Golang 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT