GO로 네이버 웹툰들의 평점 정보 가져오기

Naver Webtoon All rating crawler - 12/16/2019 ~ 12/19/2019

요일별 모든 웹툰들의 전체 화의 평점을 각 파일별로 나누어 크롤링해오는 프로그램

//스크래핑 대상 URL

const (
	urlRoot    = "https://comic.naver.com/webtoon/weekday.nhn"
	urlSubRoot = "https://comic.naver.com"
)

📦패키지

"github.com/yhat/scrape"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"

1일차 - 🌟네이버 웹툰 메인페이지서 모든 웹툰을 고루틴(쓰레드)를 통해 이동 후 페이지 평점 정보를 가지고 옴
2일차 - 🤹생각보다 너무 쉬워서 모든 웹툰의 최근 10화를 고루틴(쓰레드)를 통해 2차 이동 후 참여자 수도 가지고 옴
3일차 - 🐛자꾸 에러가 떠서 로그를 찍어보다가 19금 웹툰에서 막히는 것을 발견하고 고침
4일차 - 👨‍💻마지막으로 파일 입출력 처리에 관한 문제를 발견하고 오류 수정

모든 웹툰을 고루틴을 통해 이동하는 코드

//class가 title인(모든) 웹툰들 대상으로 원하는 URL파싱 후 반환하는 함수
func parseMainNodes(n *html.Node) bool {
	if n.DataAtom == atom.A && n.Parent != nil {
		return scrape.Attr(n, "class") == "title"
	}
	return false
}
urlList := scrape.FindAll(root, parseMainNodes)

	//웹툰들 전부 긁어와서 for range로 순회
	for _, link := range urlList {
		// //대상 URL 출력
		// fmt.Println("Mon Link : ", link, idx)
		// //웹툰 제목
		// fmt.Println(scrape.Attr(link, "title"))

		fileName := scrape.Attr(link, "title")
		fmt.Println("filename is : ", fileName)

		//작업 대기열에 고루틴이 다 끝날때까지 기다릴 수 있게 추가
		wg.Add(1) //Done 개수와 일치

		//고루틴 시작 -> 작업 대기열 개수와 같아야 함.
		go scrapContents(scrape.Attr(link, "href"), fileName)
	}

Screen Shot 2019-12-19 at 20 26 54

고루틴이 있다면 동기화를 해야함

//동기화를 위한 작업 그룹 선언
var wg sync.WaitGroup
var mutex = &sync.Mutex{}

에러체크

//에러체크할 함수 선언하여 계속 사용해줌.
func errCheck(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

모든 웹툰의 최근 10화 웹툰을 고루틴을 통해 들어가는 코드

//<td class="title"> 최근 10화 웹툰 사이트들 태그 긁어오는 함수
func parseSubNodes(n *html.Node) bool {
	// return n.Parent.DataAtom == atom.Td && scrape.Attr(n, "class") == "title"
	if n.DataAtom == atom.A && n.Parent != nil {
		return scrape.Attr(n.Parent, "class") == "title"
	}
	return false
}
recentList := scrape.FindAll(root, parseSubNodes)

	//parseSubNodes 함수를 사용해서 원하는 노드 순회(평점 긁어오기)하면서 출력
	//<td class="title"> 최근 10화 웹툰 사이트 태그
	for _, link := range recentList {
		//동기화
		wg.Add(1)
		mutex.Lock()
		//해당 데이터 출력
		go scrapRatingType(scrape.Attr(link, "href"), fn)
		//파싱 데이터 -> 버퍼에 기록
		// w.WriteString(scrape.Text(g) + "\r\n")
	}
	// w.Flush()

Screen Shot 2019-12-19 at 20 26 19

웹툰들의 평점과 참여자 수 정보를 가지고오는 코드

//<div class="..." id="topTotalStarPoint"> 가 있는 코드들 긁어오는 함수
func parseStarNodes(n *html.Node) bool {
	return n.DataAtom == atom.Div && scrape.Attr(n, "id") == "topTotalStarPoint"
}

Screen Shot 2019-12-19 at 20 26 41

웹툰이름.txt 파일에 평점과 참여자 수를 자동으로 작성해주는 코드

//파일 스크림 생성(열기) -> 파일명, 옵션, 권한
	file, err := os.OpenFile("/Users/jejeongmin/documents/go/src/NaverWebtoon_crawler/Scrape/"+fn+".txt", os.O_APPEND|os.O_CREATE|os.O_RDWR, os.FileMode(0777))
	//에러체크
	errCheck(err)

	//메소드 종료 시 파일 닫아야 함
	defer file.Close()

	//쓰기 버퍼 선언
	w := bufio.NewWriter(file)

	for _, g := range scrape.FindAll(root, parseStarNodes) {
		//URL 및 해당 데이터 출력
		fmt.Println("result : ", scrape.Text(g))
		//파싱 데이터 -> 버퍼에 기록
		w.WriteString(scrape.Text(g) + "\r\n")
	}
	w.Flush()

Screen Shot 2019-12-19 at 19 59 29

😞아쉬웠던 점 + 고루틴(쓰레드)의 장점

19살이 안되서 19금웹툰의 정보를 갖고오지 못했다. 정보를 갖고오지 못하는 에러가 났음에도 다른 웹툰들의 정보를 모두 긁어올 수 있었던 건 고루틴(쓰레드)를 활용하였기 때문이다.

Categories:

Updated:

Leave a comment