728x90
동적 웹크롤링 selenium 을 이용하여 데이터를 수집하였습니다.
○ 라이브러리 설치
import pandas as pd
# 동적 웹 페이지 처리를 위한 라이브러리
from selenium import webdriver
# 웹페이지 내에서 데이터 추출을 위한 라이브러리
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from urllib3.exceptions import MaxRetryError
# 시간 라이브러리 추가
import time
import random
○ 윈도우 정보 가져오기 및 페이지 전환
def new_handle():
board_handle = driver.window_handles[-1]
driver.switch_to.window(board_handle)
time.sleep(0.2+random.random()/4)
○ 제품 상세 정보(제품명, 사진, 가격, 정보) 가져오는 함수
def product_info():
try:
# 제목
title_path = '#blog_content > div.summary_info > div.top_summary > h3 > span'
# title_element = driver.find_element(By.CSS_SELECTOR,title_path)
title_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, title_path))
)
title = title_element.text
# 사진
image_path = '#baseImage'
# image_element = driver.find_element(By.CSS_SELECTOR,image_path)
image_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, image_path))
)
image = image_element.get_attribute('src')
# 가격
price_path = '#blog_content > div.summary_info > div.detail_summary > div.summary_left > div.lowest_area > div.lowest_top > div.row.lowest_price > span.lwst_prc > a > em'
price_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, price_path))
)
price = price_element.text
# 상품정보
infomation_path = '#productDescriptionArea > div > div.prod_spec > table > tbody'
infomation_element = driver.find_element(By.CSS_SELECTOR,infomation_path)
infomation = infomation_element.text
# 줄바꿈 없이 저장
# infomation = infomation.replace('\n','')
# 리스트형태로 한 행씩 저장
infomation = infomation.split("\n")
print(f"title: {title}")
print(f"price: {price}")
print(f'image : {image}')
print(f"infomation: {infomation}")
return {'title' : title, 'price' : price, 'image' : image, 'infomation' : infomation}
except StaleElementReferenceException as S:
time.sleep(2)
new_handle()
print(f'move_page error : {S}')
pass
except Exception as e:
new_handle()
print(e)
pass
finally:
new_handle()
○ 페이지( 쪽수) 넘기는 함수
def move_page(function):
cnt = 0
n = 1
while n < 11:
try:
if n > 10:
break
n += 1
function()
this_page = f'#paginationArea > div > div > a.snum.now_spage.click_log_page'
this_page_elemnet = driver.find_element(By.CSS_SELECTOR,this_page)
# 현재 페이지 번호
# current_page = int(this_page_elemnet.text[-1])
# print(current_page)
# 현재 페이지 번호 + 1 의 경로
#paginationArea > div > div > a:nth-child(3)
next_page = f'#paginationArea > div > div > a:nth-child({(int(this_page_elemnet.text)+1)%10})'
# WebDriverWait를 사용하여 다음 페이지로 넘어갈 때까지 대기 - 이를 통해 페이지 넘어가지 않는 오류 해결
page_bar_next = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, next_page))
)
# page_bar_next = driver.find_element(By.CSS_SELECTOR,next_page)
page_bar_next.click()
new_handle()
time.sleep(10)
# print(f'지금 누른 페이지 : {page_bar_next.text}')
# cnt +=1
# n += 1
except StaleElementReferenceException as S:
time.sleep(2)
new_handle()
print(f'move_page error : {S}')
continue
except Exception as e:
new_handle()
print(e)
cnt +=1
print(f'에러카운트 : {cnt}')
pass
finally:
new_handle()
# print(f'에러카운트 : {cnt}')
# if cnt == 2:
# break
○ 상품 하나씩 링크로 들어가기 및 나오기
# 상품
def product():
try:
path = '#productListArea > div.main_prodlist.main_prodlist_list > ul> li > div > div.prod_info > p > a'
# 모든 링크 찾기
links = driver.find_elements(By.CSS_SELECTOR, path)
for link in links:
link_id = link.get_attribute('id')
if 'adSmartArea' in link_id:
continue
# 새탭의 링크 열기
link.send_keys(Keys.CONTROL + Keys.RETURN)
# 새로 열린 탭으로 전환하기 전에 대기
WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2))
# 새로 열린 탭으로 바꾸기
# tab_handle = driver.window_handles[-1]
# driver.switch_to.window(tab_handle)
new_handle()
# 페이지 로딩시간 벌어주기
time.sleep(3 + random.random())
# 변경사항 - def product Error: 'NoneType' object is not subscriptable 오류해결
info = product_info()
if info is not None and 'title' in info and 'image' in info and 'price' in info and 'infomation' in info:
title = info['title']
image = info['image']
price = info['price']
infomation = info['infomation']
f.write(f'{title}\t{image}\t{price}\t{infomation}\n')
else:
print("product_info() 함수에서 유효한 정보를 얻을 수 없습니다.")
f.write(f'{title}\t{image}\t{price}\t{infomation}\n')
# 탭 닫기
driver.close()
# 원래 페이지로 바꾸기
# tab_handle = driver.window_handles[0]
# driver.switch_to.window(tab_handle)
new_handle()
except StaleElementReferenceException as S:
driver.refresh()
time.sleep(2)
print(f"def product Stale Error : {S}")
new_handle()
pass
except MaxRetryError as retry:
print('MaxRetryError :' , retry)
driver.refresh()
time.sleep(2)
new_handle()
pass
except ConnectionError as ce:
print('ConnectionError :' , ce)
driver.refresh()
time.sleep(2)
new_handle()
pass
except Exception as e:
print(f"def product Error: {e}")
f.close()
driver.quit()
○ 함수 호출 및 텍스트 파일로 데이터 저장하기
driver = webdriver.Chrome()
driver.get("https://search.danawa.com/dsearch.php?query=%EC%A0%84%EA%B8%B0%EB%B0%A5%EC%86%A5&originalQuery=%EC%A0%84%EA%B8%B0%EB%B0%A5%EC%86%A5&previousKeyword=%EC%A0%84%EA%B8%B0%EB%B0%A5%EC%86%A5&checkedInfo=N&volumeType=vmvs&page=22&limit=40&sort=saveDESC&list=list&boost=true&tab=goods&addDelivery=N&coupangMemberSort=N&mode=simple&isInitTireSmartFinder=N&recommendedSort=N&defaultUICategoryCode=102123&defaultPhysicsCategoryCode=1%7C46%7C48%7C0&defaultVmTab=2384&defaultVaTab=360775&isZeroPrice=Y&quickProductYN=N")
if __name__ == '__main__':
time.sleep(0.5+random.random()/4)
try:
f = open('./data/전기밥솥6.txt', "a", encoding='UTF-8')
move_page(product)
print('텍스트 닫힘')
finally:
f.close()
driver.quit()
- 페이지가 넘어갈때까지 기다려주는 WebDriverWait 을 이용하여 페이지가 시간이 충분하지 않아서 넘어가지 않는 오류 해결하였습니다
- 페이지 경로가 1부터 10까지 와 11부터 20까지가 동일하게 1부터 10번의 n-th child로 되어있어 현재 페이지 번호 +1에서 10을 나눈것의 나머지로 해결하였습니다
- 상품 탭 중간에 id만 다른 광고가 있어 오류가 발생하여 id를 통해 구분하여 adSmartArea면 건너뛰도록 하여 해결하였습니다
728x90
'Project' 카테고리의 다른 글
[전자제품 쇼핑몰] 데이터베이스에 데이터 저장하기 & 데이터 생성하기 (1) | 2024.01.28 |
---|---|
[전자제품쇼핑몰] 데이터 전처리 - 웹크롤링 데이터 전처리 (3) | 2024.01.24 |
[데이터분석] 국내 여행지역 관심도 분석(5) - 지도 시각화(1) (5) | 2024.01.07 |
[데이터 분석] 국내 여행지역 관심도 분석(4) (3) | 2024.01.06 |
[데이터 분석] 국내 여행지역 관심도 분석(3) (2) | 2023.12.17 |