본문 바로가기
수업(국비지원)/Python

[Python] 한글분석 예제 - 맛집리뷰용어 분석하기(크롤링)

by byeolsub 2023. 4. 27.

📌

# 카카오맵을 크롤링하여 맛집리뷰에 사용되는 용어분석하기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import re
import time

path = "c:setup/chromedriver.exe"
source_url = "<https://map.kakao.com/>"
driver = webdriver.Chrome(path)
driver.get(source_url) # 웹브라우저에 카카오맵지도 표시
time.sleep(1)
# searchbox : html 중 id="search.keyword.query"인 태그
searchbox = driver.find_element(By.ID,"search.keyword.query")
searchbox.send_keys("강남역 고기집") 
time.sleep(1)
# searchbutton : 검색버튼. id="search.keyword.submit" 
searchbutton = driver.find_element(By.ID,"search.keyword.submit")
# arguments[0].click() : searchbutton 클릭
driver.execute_script("arguments[0].click();", searchbutton)
time.sleep(1)
# 브라우저에 있는 현재화면의 html소스를 html변수에 저장
html = driver.page_source
# html문장을 분석
soup = BeautifulSoup(html, "html.parser")
# moreviews : class="moreviews" a 태그목록. 상세보기들 목록 
moreviews = soup.find_all\\
    (name="a", attrs={"class":"moreview"})
page_urls = [] # 강남역 고기집의 상세보기 href 목록
for moreview in moreviews :
    page_url = moreview.get("href") # a 태그의 htrf 속성값 
    page_urls.append(page_url)
driver.close() # 브라우저 종료
print(page_urls)
print(len(page_urls))

#########
# 장인닭갈비 후기 읽어서 DataFrame으로 저장
columns = ['score','review']
page = '<https://place.map.kakao.com/95713992>'
df = pd.DataFrame(columns=columns) # 컬럼만 존재
driver = webdriver.Chrome(path) # 브라우저 실행
driver.get(page) # 고기집 상세화면
time.sleep(2)
another_reviews = driver.find_element(By.CSS_SELECTOR,"span.txt_more")
print(another_reviews.text)
for i in range(11) : # 11번을 후기 더보기 텍스트를 클릭
    time.sleep(2)
    another_reviews = driver.find_element(By.CSS_SELECTOR,"span.txt_more")
    try :
        another_reviews.text.index('후기 더보기')
        another_reviews.click() # 후기 더보기 클릭
    except : 
        break # 후기 더보기 값이 없는 경우 오류 발생.
              # 오류 발생시 반복문 종료
time.sleep(2)
html = driver.page_source # html 소스데이터
soup = BeautifulSoup(html,'html.parser')
contents_div = soup.find(name="div", attrs={"class":"evaluation_review"}) # 리뷰 영역.
reviews = contents_div.find_all(name="p", attrs={"class":"txt_comment"}) # 리뷰 목록
rates = contents_div.find_all(name="span", attrs={"class":"inner_star"}) # 별점값 목록

for rate, review in zip(rates, reviews) : # (별점목록, 리뷰목록)  
    rate_style = rate.attrs['style'].split(":")[1] # width : 20%
    rate_text = int(rate_style.split("%")[0])/20 #1
    row = [int(rate_text), review.find(name="span").text]
    series = pd.Series(row, index=df.columns) # score, review 인덱스 설정. 시리즈 객체
    df = df.append(series, ignore_index=True)
driver.close()
df.info()
df.head()
df.score.value_counts()

 

###########################################
# 상세보기에 조회된 고기집 목록을 조회
columns = ['score','review']
df = pd.DataFrame(columns=columns) # 컬럼만 존재
driver = webdriver.Chrome(path)
page_urls
### 반복문 시작
for idx, page in enumerate(page_urls) :
    print(idx + 1, page)
    driver.get(page) # 고기집 상세화면
    time.sleep(2)
    another_reviews = driver.find_element(By.CSS_SELECTOR,"span.txt_more")
    for i in range(20) :
        time.sleep(2)
        another_reviews = driver.find_element(By.CSS_SELECTOR,"span.txt_more")
        try :
            another_reviews.text.index('후기 더보기')
            another_reviews.click() # 후기 더보기 클릭
        except : 
            break
    time.sleep(2)
    html = driver.page_source # html소스데이터
    soup = BeautifulSoup(html,'html.parser')
    try :
      contents_div = soup.find(name="div", attrs={"class":"evaluation_review"}) # 리뷰 영역.
      reviews = contents_div.find_all(name="p", attrs={"class":"txt_comment"}) # 리뷰 목록
      rates = contents_div.find_all(name="span", attrs={"class":"inner_star"}) # 별점값 목록
      
      for rate, review in zip(rates, reviews) : # (별점목록, 리뷰목록)  
          rate_style = rate.attrs['style'].split(":")[1] # width : 20%
          rate_text = int(rate_style.split("%")[0])/20 #1
          row = [int(rate_text), review.find(name="span").text]
          series = pd.Series(row, index=df.columns) # score, review 인덱스 설정. 시리즈 객체
          df = df.append(series, ignore_index=True)
    except :
       continue
### 반복문 종료      
driver.close()
df.info()
df.head()
df.score.value_counts()

# 별점이 5,4 => 긍정(1)
# 별점이 1,2,3 => 부정(0)
df["y"] = df["score"].apply(lambda x : 1 if float(x)>3 else 0)
df.info()
df["y"].value_counts()

# df 데이터를 review_data.csv 파일로 저장하기
df.to_csv("data/review_data.csv", index=False)