본문 바로가기
Appz Knowledge/Python

Crawling/크롤링 무작정 따라하기 - Naver 쇼핑편

by 스쳐가는인연 2023. 1. 28.

Note. 2023/01/28 기준, Naver 사이트 변경으로 인해 크롤링 강의들이 동작하지 않는 경우가 많음에 따라 시점 기록

 

requests library를 공부(?)하다 crawling으로 잠시 외도하여... soup를 보다 Selenimum까지 흘러와버린 ...

따라만 해도 동작한다는 것이 이렇게 신기할 줄이야 ... 불행히도 전에 본 몇 개 강의는 다 동작을 안해서...

(당연히 된다는 상식을 깨버린 ...)

우찌되었던... 메타코드 소현쌤에 감사를 ...

 

크롤링을 찾다보니, 이런 저런 말들이 많은 듯 ...  robots.txt 파일도 열람해보고 ... (까막눈 ...)

https://searchadvisor.naver.com/guide/seo-basic-robots

https://www.naver.com/robots.txt 

 

 

Selenium # 동적 html 사이트 크롤링
https://www.selenium.dev/
- url 주소가 변경되지 않지만 Data가 변경되는 경우
- 로그인, 버튼 조작, 스크롤, 검색 등 어떤 동작을 수행해야 원하는 데이터를 추출할 수 있는 경우

Note. chrome brower를 이용하여 진행됨에 chromedriver 함께 업그레이드 해야함.
https://chromedriver.chromium.org/downloads

 

# pip install selenium
# pip install chromedriver-autoinstaller  # driver 자동 관리

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

 

# 크롤러 동작을 위해 브라우저 드라이버 확인

chrome_ver = chromedriver_autoinstaller.get_chrome_version().split('.')[0]

 

try:
    crawler = webdriver.Chrome(f'./{chrome_ver}/chromedriver.exe')

except:
    chromedriver_autoinstaller.install(True)
    crawler = webdriver.Chrome(f'./{chrome_ver}/chromedriver.exe')

 

# 크롤러를 통해 Naver 페이지 접근

crawler.implicitly_wait(10)

crawler.get('https://www.naver.com/")

 

Naver 쇼핑
Naver 쇼핑의 Xpath 얻는 방법

# Naver 쇼핑 선택 - Chrome 브라우저에서 개발자모드 <F12>를 통해 XPath를 확인 후 입력/전달
crawler.find_element('xpath', '//*[@id="NM_FAVORITE"]/div[1]/ul[1]/li[5]/a').click()

 

Naver 쇼핑 > 식품 > 채소

# 식품 선택
crawler.find_element('xpath', '//*[@id="content"]/div/div[1]/div/div[1]/div/div/div[1]/ul/li[6]/button').click()

# 채소 선택
crawler.find_element('xpath', '//*[@id="content"]/div/div[1]/div/div[1]/div/div/div[2]/div[1]/ul/li[3]/a').click()

 

Naver 쇼핑 검색창

# Note. 검색창의 경우, 단순 선택이 아니라, 검색어 입력 및 검색 실행의 일련의 동작이 필요

# 검색창 선택 및 고구마 검색
engine = crawler.find_element('xpath', '//*[@id="__next"]/div/div[1]/div/div[2]/div/div[2]/form/fieldset/div[1]/input')
engine.click() # 검색창 선택
engine.send_keys('고구마') # 검색어 입력
engine.send_keys(Keys.ENTER) # 검색 수행

# 리뷰 많은 순 선택
crawler.find_element('xpath', '//*[@id="__next"]/div/div[2]/div/div[3]/div[1]/div[1]/div/div[1]/a[4]').click()

names= [] # 고구마 판매 제목
prices= [] # 고구마 가격
review_cnts= [] # 리뷰 수
links= [] # 실 사이트 링크

 

# page 변경 부분, 1 - 3 Page까지

for i in range(1, 3):
    crawler.get('https://search.shopping.naver.com/search/all?frm=NVSHATC&origQuery=%EA%B3%A0%EA%B5%AC%EB%A7%88&pagingIndex={0}&pagingSize=40&productSet=total&query=%EA%B3%A0%EA%B5%AC%EB%A7%88&sort=rel&timestamp=&viewType=list'.format(i))

# page 스크롤 부분, 한 페이지 상에 표시되는 항목들 확인
    while True:
        bh = crawler.execute_script("return document.body.scrollHeight") # 초기 로딩된 페이지 높이, before height
        print(bh)
        time.sleep(4)
        crawler.execute_script("window.scrollTo(0, document.body.scrollHeight)") # scrolling
        time.sleep(2)
        ah = crawler.execute_script("return document.body.scrollHeight") # 스크롤 후 높이, after height
        if ah == bh:
            break
        bh = ah

 

infos = crawler.find_elements(By.CSS_SELECTOR, ".basicList_info_area__TWvzp")
for info in infos:
    try:
        name = info.find_element(By.CSS_SELECTOR, ".basicList_title__VfX3c").text
        names.append(name)
        price = info.find_element(By.CSS_SELECTOR, ".price_num__S2p_v").text
        prices.append(price)
        review_cnt = info.find_element(By.CSS_SELECTOR, ".basicList_num__sfz3h").text
        review_cnts.append(review_cnt)
        link = info.find_element(By.CSS_SELECTOR, "a.basicList_link__JLQJf").get_attribute("href")
        links.append(link)

    except:
        print('exception')


crawler.close() # 크롤러 종료

df = pd.DataFrame({'name':names, 'price':prices, 'review_cnts':review_cnts, 'link':links})
print(df)

# csv 형태로 변환, utf8 형태로 인코딩하고, ','로 구분함
df.to_csv('./best_sweet_potato.csv', sep = ",", encoding= "utf-8-sig")

 

# Optional, 시각화 해보기
from wordcloud import WordCloud

wc = WordCloud(font_path = "./malgun.ttf", colormap = "PuBu", width = 500, height = 500)
wc.generate(str(df['name']))
wc.to_file('sweet_potato.png')

sweet_potato.png


참고자료:
https://www.youtube.com/watch?v=a60FScYiuio

 

 

 

 

 

반응형