-
[python] Review web Crawling 쉽게 쉽게!카테고리 없음 2020. 3. 4. 22:42
인턴과정을 진행중, Firebase의 기반으로 수집된 앱 사용성 데이터 이외에 정성적인 데이터에 대한 분석에 관심이 갔다.
앱에서 정석적인 데이터라하면, 사용자자 앱마켓에 올리는 리뷰 의견이 대표적으로 볼 수 있다.
이번 시간에는 구글 앱에서 리뷰에 대한 크롤링 작업이다. 참고할 좋은 자료가 있어 이해한 과정을 순서대로 적어볼 생각이다.
from bs4 import BeautifulSoup as BS
from selenium import webdriver
import re
from selenium.webdriver.common.keys import Keys
import time
import csv일단, 웹 크롤링을 위해 셀레니움 webdriver와 beautifulsoup 라이브러리이다.
F12를 눌러보면, 웹화면 구조를 확인 할 수 있는데, 웹 드라이버는 웹에 있는 데이터 소스를 긁어오기 위해 사용된다. beautifulsoup의 경우, 긁어온 데이터를 'parsing'이란 과정을 통해, 쉽게 원하는 요소를 뽑아낼 수 있도록 정제해주는 역할을 한다.
# webdriver 설치 여기서!
링크: https://beomi.github.io/2017/02/27/HowToMakeWebCrawler-With-Selenium/
path = 'C:/Users/ghkdn/Jupyter/chromedriver_win32/chromedriver'
driver = webdriver.Chrome(executable_path=path)
driver.get('https://play.google.com/store/apps/details?id=com.estsoft.pawever&showAllReviews=true')
driver.implicitly_wait(3) # 3초 기다림
search_result1 = driver.find_element_by_xpath('//*[@id="fcxH9b"]/div[4]/c-wiz/div/div[2]/div/div[1]/div/div/div[1]/div[2]/c-wiz/div[1]/div/div[1]/div[2]')
search_result1.click()
search_result2 = driver.find_element_by_xpath('//*[@id="fcxH9b"]/div[4]/c-wiz/div/div[2]/div/div[1]/div/div/div[1]/div[2]/c-wiz/div[1]/div/div[2]/div[1]')
search_result2.click()이전 단계에서 설치한 webdriver의 설치 경로를 적어준 뒤, driver 객체를 형성하여, 크롤러를 실행할 준비를 한다.
여기서 핵심은 driver.find_element_by_xpath("경로")를 작성해주면, 자동으로 해당 경로로 움직이게 만들어 줄 수 있다.
특정한 화면 내에서 웹크롤링을 해야할 경우, 유용하다.
SCROLL_PAUSE_TIME = 0.5
while (True):
print("..crawling")
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
try:
#버튼찾기
element = driver.find_element_by_xpath('//div[@class="U26fgb O0WRkf oG5Srb C0oVfc n9lfJ"]')
# 아래 것도 가능
#element = driver.find_element_by_xpath('/html/body/div[1]/div[4]/c-wiz/div/div[2]/div/div[1]/div/div/div[1]/div[2]/div[2]/div')
if (element is not None):
print("complete")
element.click()
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
break
except Exception:
continue
# review_crawling: https://saintbeller96.tistory.com/10?category=751441구글 앱마켓의 경우, 리뷰가 스크롤을 내릴때마다 연장되고 '더보기' 버튼이 아래에 위치해 있다. 웹크롤러를 전체 페이지를 긁어오기 때문에, 화면 끝까지 보여줄 필요가 있다.
따라서 다음 코드는 이전에 사용했던, driver.find_element_by_xpath("경로") 패턴을 이용하여 버튼을 누르고 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") 을 이용해, 스크롤을 내려 최하단까지 내려가게 만든다.
html = driver.page_source
soup = BS(html,'lxml')
div_reviews = soup.find_all("div", {"class":"d15Mdf bAhLNe"})
#driver.quit() #웹화면 들어간 후, 3초뒤 나가기
reviews = []
for div in div_reviews:
users = div.find('span',{'class':'X43Kjb'}).get_text()
grade = len(div.find_all('div',{'class' : 'vQHuPe bUWb7c'}))
date_text = div.find('span',{"class":"p2TkOb"}).get_text()
t = re.findall(r"\d*\.\d+|\d+",date_text)
date = '{0}-{1}-{2}'.format(t[0],t[1],t[2])
good = div.find('div',{"class":"jUL89d y92BAb"}).get_text()
content = div.find('span',{'jsname':'bN97Pc'}).get_text()
content.encode("utf-8")
reviews.append((date,users,grade,good,content))전체 화면을 구성했을 경우,다음은 'parsing'에 대한 과정이다. webdriver를 통해 가져온 전체 지저분한 데이터를 일정한 기준에 따라 뽑아낼 수 있다. soup.find_all을 통해, div에서 해당 key값을 지닌 클래스에 있는 값을 전부 긁어온뒤, 안에 있는 데이터들에 대하여 다시 클래스 키값을 지정하여, 원하는 데이터를 선별할 수 있다. 이때, get_text()를 붙여주면, 텍스트 자료만 뽑아낼 수 있다.
with open("finish_file.csv","wt",encoding='utf-8',newline='') as file:
csvWriter = csv.writer(file)
csvWriter.writerow(["날짜","사용자","평점","공감수","내용"])
for rev in reviews:
csvWriter.writerow(rev)그 후, 로컬 파일 csv로 저장하고 싶다면, writerow에서 컬럼명을 지정하고 for문을 반복하며, 위에서 긁어온 레코드를 작성해주면 된다.