[Golang] colly를 이용한 넷플릭스 top10 수집 예제

반응형

colly는 go로 만들어진 Scraping Framework이다.

사용하기도 정말 쉽고 편하다.

colly를 이용해 넷플릭스 영화 주간 순위 top 10의 제목을 수집하는 예제를 해보자.

우선 colly의 사용법을 간단하게 알아보자.

 


colly 사용법

사용하기 위해서는 아래와 같이 import를 추가해야 한다.

import "github.com/gocolly/colly"

Collector

c := colly.NewCollector()

colly를 사용하기 위해서는 우선 lcolly.NewCollector() 함수를 호출해 *colly.Collector object
를 초기화해줘야 한다.

Visit

c := colly.NewCollector()

// Start scraping on https://hackerspaces.org
c.Visit("https://hackerspaces.org/")

c.Visit() 를 이용해서 수집할 페이지에 방문한다.

Callbacks

여러 콜백 함수들을 이용해 수집 작업이나 에러 핸들링 같은 작업을 할 수 있다.

필요한 콜백 함수를 생성한 collector에서 붙여서 호출하면 된다.

c.OnRequest(func(r *colly.Request) {
    fmt.Println("Visiting", r.URL)
})

c.OnError(func(_ *colly.Response, err error) {
    log.Println("Something went wrong:", err)
})

c.OnResponseHeaders(func(r *colly.Response) {
    fmt.Println("Visited", r.Request.URL)
})

c.OnResponse(func(r *colly.Response) {
    fmt.Println("Visited", r.Request.URL)
})

c.OnHTML("a[href]", func(e *colly.HTMLElement) {
    e.Request.Visit(e.Attr("href"))
})

c.OnHTML("tr td:nth-of-type(1)", func(e *colly.HTMLElement) {
    fmt.Println("First column of a table row:", e.Text)
})

c.OnXML("//h1", func(e *colly.XMLElement) {
    fmt.Println(e.Text)
})

c.OnScraped(func(r *colly.Response) {
    fmt.Println("Finished", r.Request.URL)
})

콜백 함수의 호출 순서는 아래와 같다.

OnRequest > OnError > OnResponseHeaders > OnResponse > OnHTML > OnXML > OnScraped

 

 


수집 예제

이제 넷플릭스 한국 주간 top 10 사이트에서 영화 목록을 수집하는 예제를 해보자.

사이트에 들어가면 하단에 있는 테이블을 타겟으로 이번 주 영화 top 10 순위와 제목을 출력해보자.

아래 이미지에서 빨간 박스에 있는 테이블이다.

 

 

1. top 10 순위와 제목 출력

package main

import (
    "fmt"

    "github.com/gocolly/colly"
)

func main() {
    c := colly.NewCollector()

    c.OnHTML("table", func(e *colly.HTMLElement) {
        e.ForEach("tbody > tr ", func(_ int, element *colly.HTMLElement) {
            rank := element.ChildText("td.hidden")
            title := element.ChildText("td.leading-tight")
            fmt.Println(rank, title)
        })
    })

    c.Visit("https://top10.netflix.com/south-korea")
}

Output

1 The Adam Project
2 Don't Breathe 2
3 Black Crab
4 The Pirates: The Last Royal Treasure
5 Mission: Impossible - Fallout
6 Anarchist from Colony
7 Perhaps Love
8 Rescued by Ruby
9 Escape Room: Tournament Of Champions
10 The Bombardment

출력된 결과를 보면 알겠지만 영화 제목이 영어로 나온다.

사이트 자체에서 언어를 영어와 스페인어만 제공해주고 있다.

 

 

 

2. 제목 한국어로 출력

한국어 제목으로 출력해보는 예제를 진행해보자.
사이트 중앙에 위치한 리스트에서 Watch now 버튼을 클릭하면

아래와 같이 해당 영화의 한국어 페이지로 리다이렉트 되는 것을 확인할 수 있다.

 

Watch now 버튼에 연결된 link들을 수집해서 출력해보자.

package main

import (
    "fmt"
    "github.com/gocolly/colly"
)

func main() {
    c := colly.NewCollector()

    c.OnHTML("ul.absolute", func(e *colly.HTMLElement) {
        for _, link := range e.ChildAttrs("a", "href") {
            fmt.Println(link)
        }
    })

    c.Visit("https://top10.netflix.com/south-korea")
}

Output

https://www.netflix.com/title/81309354
https://www.netflix.com/title/81415088
https://www.netflix.com/title/80220426
https://www.netflix.com/title/81336431
https://www.netflix.com/title/80236314
https://www.netflix.com/title/80197491
https://www.netflix.com/title/81580568
https://www.netflix.com/title/81107362
https://www.netflix.com/title/81198941
https://www.netflix.com/title/81186240

출력된 결과를 보면 한국어 페이지가 아닌 것을 알 수 있다.

이대로 해당 링크를 방문해서 제목을 수집하면 처음 했던 것과 같이 영어 제목으로 출력된다.

그러므로 방문할 때 헤더에 accept-language 설정을 한국어로 설정해주면 된다. 

그러면 https://www.netflix.com/kr/title/81309354 로 리다이렉트 된다.

 

 

 

이제 방문할 링크들을 수집했으니 해당 링크들을 방문해서 제목을 출력해보자.

수집한 링크를 방문해서 영화 제목만을 수집하는 collector를 하나 만들어준다.

 

Clone() 함수를 이용해서 같은 설정을 공유하면서 콜백 함수를 공유하지 않는 collector를 만들 수 있다.

 

그리고 빨간 박스를 타겟으로 텍스트를 수집해서 출력하면 된다.

package main

import (
    "fmt"
    "github.com/gocolly/colly"
)

func main() {
    c := colly.NewCollector()
    titleCollector := c.Clone()

    c.OnHTML("ul.absolute", func(e *colly.HTMLElement) {
        for rank, link := range e.ChildAttrs("a", "href") {
            fmt.Printf("%d ", rank+1)
            titleCollector.Visit(link)
        }
    })

    titleCollector.OnRequest(func(r *colly.Request) {
        r.Headers.Set("accept-language", "ko")
    })

    titleCollector.OnHTML("h1.title-title", func(e *colly.HTMLElement) {
        fmt.Println(e.Text)
    })

    c.Visit("https://top10.netflix.com/south-korea")
}

위에서도 설명했으니 헤더를 추가해준다.

 

Output

1 애덤 프로젝트
2 맨 인 더 다크 2
3 블랙 크랩
4 해적: 도깨비 깃발
5 미션 임파서블: 폴아웃
6 박열
7 장르만 로맨스
8 구조견 루비
9 이스케이프 룸 2: 노 웨이 아웃
10 폭격

결과를 확인해보면 원하던 대로 한국어 제목으로 출력되는 것을 확인할 수 있다.

 


참고