크롤러 만들기 [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,
})
}
비밀글 및 정규표현식으로는 제목과 본문을 읽을 수 없는 경우를 제외하고
약 186개의 게시물을 읽고 JSON으로 반환하는데 까지 걸리는 시간은 아래와 같습니다.
이 시간은 제 컴퓨터에서 대상 사이트에 접근하는 시간 + 수집하는 시간 + JSON으로 변환하는 시간 등등 모든 시간이 다 포함된 시간입니다.
이걸로 마무리가 되었네요.
아무래도 주석 한줄 없다보니 많은 사람들이 읽기 엄청 어려우셨을 겁니다...
그래도 여기까지 와주셔서 감사합니다.
질문이 있으시면 언제든지 답해드리겠습니다.
!-->!-->!-->!-->1