파이썬을 이용한 네이버 리뷰 크롤링

김잭앙·2022년 12월 21일
0

제품에 따른 리뷰 데이터를 분석하여 감성분석을 하여 점수를 매기고 시각화하는 프로젝트를 구상 중이다.

이때 카테고리를 지정하여 어느 부분에서 긍정적인 리뷰가 많이 나왔는지 알고자 한다.

주피터 노트북을 사용하였다.

네이버 리뷰에서는 카테고리(만족도, 소재, 가격, 디자인 등)별로 구분되어 볼 수 있다.

이 카테고리에 따라 리뷰를 크롤링하는 코드를 작성한다.

먼저 크롤링에 필요한 라이브러리를 import 하자!

그 전에 크롬드라이버가 없으면 설치하여 위치에 넣어준다.

from selenium import webdriver as wb
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import pandas as pd

혹시 import가 안되면

!pip install selenium 을 입력하여 셀레니움을 주피터노트북에 설치한다.

먼저 리뷰에 활용할 url을 리스트에 저장하고 코드를 함수화시키고, 변수에 리스트와 csv파일로 저장할 파일의 이름을 입력하여 현재 폴더에 저장하도록 한다.

def review_to_csv(url_list,csv_name):
	# 코드 입력

review_to_csv(url_list,"리뷰데이터")

리뷰 데이터들을 담을 result 리스트를 생성하고 크롬을 실행한다.

result = []

for j in range(len(url_list)):
    
    driver = wb.Chrome('./chromedriver.exe')
    driver.get(url_list[j])
    driver.implicitly_wait(5)   # 크롬이 열리는 시간을 고려

    #제품 이름 저장
    product_name = driver.find_elements(By.CSS_SELECTOR, '#__next > div > div.style_container__D_mqP > div.style_inner__ZMO5R > div.top_summary_title__ViyrM > h2')[0].text
    #제품 가격 저장
    product_price = driver.find_elements(By.CSS_SELECTOR, '#__next > div > div.style_container__D_mqP > div.style_inner__ZMO5R > div.style_content_wrap__78pql > div.style_content__v25xx > div > div.summary_info_area__NP6l5 > div.lowestPrice_price_area__VDBfj > div.lowestPrice_low_price__Ypmmk > em')[0].text
    
    # 카테고리 저장 부분
    keyword_list_css = '#section_review > div.filter_sort_group__2G1QI > div.filter_evaluation_tap__V1J3G > div > ul > li > a'
    # 인덱스가 0인 부분은 전체리뷰를 읽어오기 때문에 1부터 시작
		keyword_list = driver.find_elements(By.CSS_SELECTOR, keyword_list_css)[1:]

이하 코드

데이터를 문자열로 한번에 저장하고 split 으로 나눈 후 리스트에 담아 엑셀로 저장하는 로직을 만들었다.

# 카테고리 돌면서 데이터 저장
    for k in keyword_list:
        time.sleep(0.5)
        k.send_keys(Keys.ENTER)  # 카테고리 클릭
        time.sleep(1) # 안하면 에러남

        do = 0  # 반복문 탈출을 위한 임시 변수

        ## -------페이지 넘기기-------
        # 페이지 바가 있으면 변수에 페이지 바, 현재페이지를 저장
        try:
            page_bar = driver.find_elements(By.CSS_SELECTOR,'#section_review > div.pagination_pagination__JW7zT')[0]
            pages = page_bar.find_elements(By.CSS_SELECTOR,'a')
            page_now = page_bar.find_elements(By.CSS_SELECTOR,'a.pagination_now__Ey_sR')[0].text.replace('현재 페이지\n','')

            while do==0:
                if do==1:
                    break
                # 페이지 바 순회
                page_bar = driver.find_elements(By.CSS_SELECTOR,'#section_review > div.pagination_pagination__JW7zT')[0]
                pages = page_bar.find_elements(By.CSS_SELECTOR,'a')
                page_now = page_bar.find_elements(By.CSS_SELECTOR,'a.pagination_now__Ey_sR')[0].text.replace('현재 페이지\n','')
                page_end = pages[-1].text

                for page in pages:
                    page_num = page.text
                    if page_num in ['이전']:
                        pass
                        time.sleep(0.5)
                    elif page_num== '현재 페이지\n'+page_now:     # 현재 페이지인 경우
                        for i in range(len(driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf'))):
                            content = driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf')[i].text.replace('\n',' ')
                            score = driver.find_elements(By.CSS_SELECTOR,'span.reviewItems_average__0kLWX')[i].text[-1]
                            result.append(product_name + "||$" + k.text + "||$" + content + "||$" + score+"||$"+product_price)
                        if page_end == page_num:
                            do = 1
                            time.sleep(0.5)
                            break
                    elif page_num =='다음':
                        driver.find_elements(By.CSS_SELECTOR,'#section_review > div.pagination_pagination__JW7zT > a.pagination_next__3_3ip')[0].click()
                        page_now = str(int(page_now)+1)
                        time.sleep(0.5)
                    elif int(page_num)>int(page_now):    # 현재페이지+1 로 이동 후 크롤링
                        page_now = page_num
                        if int(page_num)%10 == 0:
                            driver.find_elements(By.CSS_SELECTOR,'#section_review > div.pagination_pagination__JW7zT > a:nth-child(10)')[0].click()
                            time.sleep(0.5)                        
                        else:
                            driver.find_elements(By.CSS_SELECTOR,f'#section_review > div.pagination_pagination__JW7zT > a:nth-child({str(int(page_num)%10)})')[0].click()
                            time.sleep(0.5)
                        for i in range(len(driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf'))):
                            content = driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf')[i].text.replace('\n',' ')
                            score = driver.find_elements(By.CSS_SELECTOR,'span.reviewItems_average__0kLWX')[i].text[-1]
                            result.append(product_name + "||$" + k.text + "||$" + content + "||$" + score+"||$"+product_price)
                        if page_end == page_num:
                            do = 1
                            time.sleep(0.5)
                            break

        except:
            # 페이지 바 없는 경우
            for i in range(len(driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf'))):
                content = driver.find_elements(By.CLASS_NAME,'reviewItems_text__XrSSf')[i].text.replace('\n',' ')
                score = driver.find_elements(By.CSS_SELECTOR,'span.reviewItems_average__0kLWX')[i].text[-1]
                result.append(product_name + "||$" + k.text + "||$" + content + "||$" + score+"||$"+product_price)
#         if k == keyword_list[-1]:
#             driver.close()

# 얻은 데이터를 컬럼 별로 자르고 csv파일로 저장
result2 = []
for r in result:
    result2.append(r.split("||$"))
result2

data1 = []
data2 = []
data3 = []
data4 = []
data5 = []
for r in result2:
    data1.append(r[0])
    data2.append(r[1])
    data3.append(r[2])
    data4.append(r[3])
		data4.append(r[4])
data1 = pd.Series(data1)
data2 = pd.Series(data2)
data3 = pd.Series(data3)
data4 = pd.Series(data4)
data5 = pd.Series(data5)

data = pd.concat([data1, data2, data3,data4,data5],axis=1)
data.columns = ['제품명','카테고리','내용','별점','가격']
data.to_csv("./"+csv_name+".csv",index=False, encoding='UTF-8-sig') 
# 인코딩을 utf-8-sig로 하면 내용에 있는 이모티콘들까지 문제없이 읽어온다.

print("종료")

안되는 부분을 조금씩 수정하다보니 중복코드도 많고 조금 복잡하다..

profile
//TODO Ready To BackEnd

0개의 댓글