티스토리 뷰

Selenium 쓰다가 Helium 쓰면 신세계를 만난 느낌이다.

코드가 굉장히 간단해진다

Helium에 관한 자세한 사용법은

https://github.com/mherrmann/selenium-python-helium

 

GitHub - mherrmann/selenium-python-helium: Selenium-python but lighter: Helium is the best Python library for web automation.

Selenium-python but lighter: Helium is the best Python library for web automation. - GitHub - mherrmann/selenium-python-helium: Selenium-python but lighter: Helium is the best Python library for we...

github.com


<크롤링 순서>

1. 매장 이름 수집

2. 해당 매장 리뷰 페이지 URL 수집('data-sid' 활용)

3. 리뷰, 별점 등을 수집하고 MySQL에 저장

 

<주의사항>

  • Helium의 기본 Chromedriver 를 변경해야 한다.
    1. 본인의 Chrome 버전을 확인한다. 
    2. Chrome 버전에 맞는 Chromedriver 를 다운받는다. 
    3. ~\Lib\site-packages\helium\_impl\webdrivers\windows 에 붙여넣는다. 

1. 매장 이름 수집

import pandas as pd
import numpy as np
from helium import *
import selenium
import time
from tqdm import tqdm
import pymysql

Python 은 3.7.13

 

def scroll():
    count=0
    while count<30:
        press(END)
        time.sleep(0.5)
        count+=1
def get_naver_title(keyword):
    global data
    data={}
    data['title']=[]
    driver=start_chrome(headless=True)
    go_to('https://pcmap.place.naver.com/accommodation/list?query='+f'{keyword}')
    next_bttn=find_all(S('.yUtES'))
    count=0
    while count<6:
        click(S('.pbshB'))
        scroll()
        time.sleep(1)
        press(HOME)
        title_list=find_all(S('.CUxF5>div>div>span.place_bluelink.moQ_p'))
        data_title=[item.web_element.text for item in title_list]
        for i in range(len(data_title)):
            data['title'].append(data_title[i])
        click(next_bttn[1])
        count+=1
    kill_browser()
    data=pd.DataFrame.from_dict(data)
    return data

driver=start_chrome(headless=True) 에서 headless 옵션을 통해 브라우저가 나타나지 않도록 하였다. 

'부산 게스트하우스'로 검색했을 시 페이지 수가 6페이지기 때문에 6페이지까지 클릭하도록 되어있다. 

매장 이름 수집 후 Dataframe 에 넣었다. 

 

1.1 리뷰페이지 URL 수집

def get_url():
    global data
    data['naver_url']=''    
    for i,keyword in enumerate(tqdm(data['title'].tolist())):
        domain=f"https://m.map.naver.com/search2/search.naver?query={keyword}&sm=hty&style=v5"
        driver=start_chrome(headless=True)
        go_to(domain)
        r=np.round(np.random.rand()+4,2)
        time.sleep(r)
        sid_list=find_all(S('._item._lazyImgContainer'))
        sid=[item.web_element.get_attribute('data-sid') for item in sid_list]
        data.iloc[i,-1]=['https://m.place.naver.com/accommodation/'+f'{sid[0]}'+'/review']
        kill_browser()
        
    return data

data에 저장된 title을 하나씩 접속하여 맨 위에 나타나는 매장의 'data-sid' 를 수집한다. 

이 'data-sid' 을 네이버지도 리뷰 페이지 url 에 붙여넣어 

해당 매장 리뷰 페이지 URL을 수집한다. 

 

2. 리뷰 별점 수집 및 MySQL INSERT

def scroll_more():
    try:
        wait_until(lambda: click(S('.fvwqf')), timeout_secs=2000, interval_secs=1.5)
    except:
        try:
            wait_until(lambda: click(S('.fvwqf')), timeout_secs=150, interval_secs=1.5)
        except:
            pass
        
def scroll_detail():
    try:
        wait_until(lambda: click(S('.Ky28p')),timeout_secs=2000, interval_secs=1.5)
    except:
        try:
            wait_until(lambda: click(S('.Ky28p')),timeout_secs=150, interval_secs=1.5)
        except:
            pass

더보기와 자세히보기를 눌러준다.

 

def get_review(place,cat):
    global data
    conn=pymysql.connect(host='localhost',user='root',password='{your_passwd}',db='{your_dbname}',charset='utf8mb4')
    cur=conn.cursor()
    for i in tqdm(range(len(data))):
        driver=start_chrome(headless=True)
        go_to(data['naver_url'][i])
        time.sleep(1)
        scroll_more()
        time.sleep(1)
        scroll_detail()
        time.sleep(1)
        review=[]
        star=[]
        title=[]
        city=[]
        category=[]
        elem=driver.find_elements_by_class_name('YeINN')
        for item in elem:
            if item.find_elements_by_css_selector('.ZZ4OK.IwhtZ>.xHaT3>.zPfVt'):
                review.append(item.find_elements_by_css_selector('.ZZ4OK.IwhtZ>.xHaT3>.zPfVt')[0].text)
            else:
                review.append('없음')
            if item.find_elements_by_css_selector('.sb8UA>.P1zUJ.HNG_1'):
                star.append(item.find_elements_by_css_selector('.sb8UA>.P1zUJ.HNG_1>em')[0].text)
            else:
                star.append('0')
        for j in range(len(review)):
            title.append(data['title'][i])
            city.append(place)
            category.append(cat)
        ress=[res for res in zip(review,star,title,city,category)]
        sql = "INSERT INTO guesthouse (review,star,title,city,category)  VALUES (%s, %s,%s,%s,%s)"
        val=ress
        cur.executemany(sql, val)
        kill_browser()
    conn.commit()
    conn.close()

더보기와 자세히보기를 누르고 

리뷰가 없으면 '없음' 

별점이 없으면 0 을 추가한다. 

 

리뷰 데이터는 미리 생성된 MySQL 테이블에 저장된다. 


def crawl(keyword,output,place='부산',cat='게스트하우스'):
    print('***get_title_start***')
    get_naver_title(keyword)
    print('***get_title_end***')
    print('***get_url_start***')
    get_url()
    data.to_csv(f'{output}/{keyword}_url.csv',index=False)
    print('***get_url_end***')
    print('***get_review_start***')
    get_review(place,cat)
    print('***get_review_end***')

3. 마치며

Helium API 사용법을 완전히 익힌 것이 아니라 Selenium 코드도 들어가있다. 

그래도 Selenium 만으로 짠 코드보단 좀 더 깨끗해진거 같다. 

아무튼, 열심히 공부해야겠다.

최근에 올라온 글
Total
Today
Yesterday