개발일지/빅데이터 댓글 시각화 프로젝트

[Python] 네이버 기사 댓글 크롤링하기 2.0v

Emil :) 2020. 7. 11. 16:08
728x90
반응형
이 포스팅은 Notion에서 작성 후 재편집하여 포스팅 된 글입니다.

 

개요


이전에 썼던 코드를 다시 쓰려고했는데, 갑자기 동작이 안됐다.

이유를 보니, 네이버의 html코드의 속성 id값이나 이런것들이 바뀌어서 그랬다.
그래서 앞으로 이런 일이 있을 떄, 대처하기 쉽게 하기 위해서도 있고.. 무엇보다 시간이 너무 오래걸렸다

555개의 댓글을 긁어모으는데 거의 40초가량이나 걸려서.. 다른방법을 모색하고 있긴 했다.
근데 너무 갓-벽한 코드가 있어서 그냥 긁어와서 url만 바꾸니 잘 작동되길래..

어떻게 돌아가는지만 공부하는 용도로 포스팅하고자 한다.

해당 코드의 전문은 다음 블로그에서 가져왔다.

blog.naver.com/seodaeho91/221273565367

 

네이버 뉴스 댓글 크롤링

안녕하세요 이번시간에는 네이버 뉴스 댓글 크롤링에 대해서 살펴보겠습니다. 빅데이터 수업의 김혜진교수...

blog.naver.com

 

진행 과정


1. webDriver가 아닌 BeautifulSoup 사용하기

먼저 Webdriver를 안쓰게 된 이유는 속도 문제이다. 그리고 나중엔 서버단에서 돌아가야되는데, webdriver는 창을 띄워서 하는거라숴.. 아무래도 나중에 문제가 많겠다 싶어서 Beautifulsoup로 하는게 낫다 싶던 도중 딱 찾았다.

애초에 네이버측에서 댓글 api를 제공하고 있었기에.. 그냥 이걸 가져오기만 하면 되는거였다.

전체 코드는 다음과 같다.

 

코드


# 댓글을 달 빈 리스트를 생성합니다.
List = []
# 라이브러리를 로드합니다.
from bs4 import BeautifulSoup
import requests
import re
import sys
import pprint

# 네이버 뉴스 url을 입력합니다.
url = "https://news.naver.com/main/read.nhn?m_view=1&includeAllCount=true&mode=LSD&mid=shm&sid1=100&oid=422&aid=0000430957"

oid = url.split("oid=")[1].split("&")[0] #422
aid = url.split("aid=")[1] #0000430957
page = 1
header = {
    "User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
    "referer": url,
}

while True:
    c_url = "https://apis.naver.com/commentBox/cbox/web_neo_list_jsonp.json?ticket=news&templateId=default_society&pool=cbox5&_callback=jQuery1707138182064460843_1523512042464&lang=ko&country=&objectId=news" + oid + "%2C" + aid + "&categoryId=&pageSize=20&indexSize=10&groupId=&listType=OBJECT&pageType=more&page=" + str(
        page) + "&refresh=false&sort=FAVORITE"
    # 파싱하는 단계입니다.
    r = requests.get(c_url, headers=header)
    cont = BeautifulSoup(r.content, "html.parser")
    total_comm = str(cont).split('comment":')[1].split(",")[0]

    match = re.findall('"contents":([^\*]*),"userIdNo"', str(cont))
    # 댓글을 리스트에 중첩합니다.
    List.append(match)
    # 한번에 댓글이 20개씩 보이기 때문에 한 페이지씩 몽땅 댓글을 긁어 옵니다.
    if int(total_comm) <= ((page) * 20):
        break
    else:
        page += 1


# 여러 리스트들을 하나로 묶어 주는 함수입니다.
def flatten(l):
    flatList = []
    for elem in l:
        # if an element of a list is a list
        # iterate over this list and add elements to flatList
        if type(elem) == list:
            for e in elem:
                flatList.append(e)
        else:
            flatList.append(elem)
    return flatList


# 리스트 결과입니다.

allCommetns = flatten(List)

print(allCommetns)
print(len(allCommetns))

이제 여기서 하나하나씩 뜯어보기로 하자.

# 댓글을 달 빈 리스트를 생성합니다.
List = []
# 라이브러리를 로드합니다.
from bs4 import BeautifulSoup
import requests
import re
import sys
import pprint

# 네이버 뉴스 url을 입력합니다.
url = "https://news.naver.com/main/read.nhn?m_view=1&includeAllCount=true&mode=LSD&mid=shm&sid1=100&oid=422&aid=0000430957"

oid = url.split("oid=")[1].split("&")[0] #422
aid = url.split("aid=")[1] #0000430957
page = 1
header = {
    "User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
    "referer": url,
}

여기까지는 큰 어려운점은 없다. 그냥 원하는 url로부터 oid, aid를 뽑아오는 것이다. 이유는 다른 곳에 붙이기 위함임.

while True:
    c_url = "https://apis.naver.com/commentBox/cbox/web_neo_list_jsonp.json?ticket=news&templateId=default_society&pool=cbox5&_callback=jQuery1707138182064460843_1523512042464&lang=ko&country=&objectId=news" + oid + "%2C" + aid + "&categoryId=&pageSize=20&indexSize=10&groupId=&listType=OBJECT&pageType=more&page=" + str(
        page) + "&refresh=false&sort=FAVORITE"
    # 파싱하는 단계입니다.
    r = requests.get(c_url, headers=header)
    cont = BeautifulSoup(r.content, "html.parser")
    total_comm = str(cont).split('comment":')[1].split(",")[0]

이부분은 c_url로 네이버 api에 접근하는 것이다. total_comm에서 split을 이용해서 문자열을 나누면 배열로 형성되는데, 이 때 comment : 를 기준으로 뒤에 있는 내용이 댓글의 실질적인 내용이고, 뒤에는 , 를 기준으로 나누기 때문에..

결과적으로 말하자면 그냥 댓글 내용 가져오는거라고 보면 된다.

이렇게 형성된 댓글들은 List라는 리스트에 들어가게 된다. 이 때 2차원 배열로 들어간다.

match = re.findall('"contents":([^\*]*),"userIdNo"', str(cont))
    # 댓글을 리스트에 중첩합니다.
    List.append(match)
    # 한번에 댓글이 20개씩 보이기 때문에 한 페이지씩 몽땅 댓글을 긁어 옵니다.
    if int(total_comm) <= ((page) * 20):
        break
    else:
        page += 1

그리고 이렇게 생성된 여러개의 List를 하나의 리스트로 묶어준다.

def flatten(l):
    flatList = []
    for elem in l:
        # if an element of a list is a list
        # iterate over this list and add elements to flatList
        if type(elem) == list:
            for e in elem:
                flatList.append(e)
        else:
            flatList.append(elem)
    return flatList

출력 결과는 다음과 같다.

# 리스트 결과입니다.

allCommetns = flatten(List)
print(allCommetns[0])
print(allCommetns[1])
# print(allCommetns)
print(len(allCommetns))

여기서 allComments뽑으면 모든 댓글들이 출력된다.

 

결과


이렇게 주루룩 뽑힌다.

다음 포스팅에선 이걸 가지고 감정분석을 해보도록 하겠다.

728x90
반응형