[WebCrawling] 웹사이트를 직접 분석해보자 -5편
Type: 데이터 수집 / 분석
주제: Web Crawling
사용 IDE: IntelliJ IDEA
사용 언어: Python
사용 패키지: selenium
GitHub Link: https://github.com/TMInstaller/WebCrawling_Myblog
설계 - 어떤 기능을 추가할까?
이번 편의 목표는 다음과 같다
목표1: 검색 첫 화면 기준 보이는 페이지 수 세는 기능 구현
목표2: 기능들 함수화 및 예외 상황에 대한 코드 보완
코드 작성
A.1. 페이지 세는 함수 제작
A.2. 페이지 정보 예외 상황 대비
B.1. 마켓컬리 크롤러 함수화
B.2. 페이지 수 만큼 반복하는 기능 넣기
B.3. 추가 변경점
A.1. 페이지 세는 함수 제작
def get_page_count(keyword):
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
browser = webdriver.Chrome(options=options)
browser.get(f"https://www.kurly.com/search?sword={keyword}")
browser.implicitly_wait(time_to_wait=3)
pages = browser.find_element(By.XPATH, '//*[@id="container"]/div/div[2]/div[3]').text
이 부분까지는 웹 페이지를 불러오는 부분이기에 그동안 해봤던 방식처럼 진행하면 된다
A.2. 페이지 정보 예외 상황 대비
# def get_page_count(keyword):
pages = pages.splitlines()
count = []
for page in pages:
count.append(int(page))
count = max(count)
if count >= 10:
return 10
else:
return count
예외 처리를 위와같이 하지 않을 시 생기는 문제점이 있다
1. 별다른 처리 없이 pages를 출력할 경우 1\n2\n3\n4\n5\n6\n7\n8\n9\n10 의 형태가 출력된다
2. String 형태이므로 저 상태에서 max를 줘 봐도 9 이상 높아지지 않는다
B.1. 마켓컬리 크롤러 함수화
def extract_kurly_items(keyword):
함수화 시켜 활용도를 높이도록 한다
B.2. 페이지 수 만큼 반복하는 기능 넣기
pages = get_page_count(keyword)
print("Found", pages, "pages")
results = []
for page in range(1, pages+1):
final_url = f"{url}{keyword}&page={page}"
page의 수를 위에 만들어두었던 함수에서 가지고 온다
몇 페이지를 찾았는 지 확인 할 코드도 넣어둔다
아래에서 진행 될 기존 코드를 페이지 수 만큼 반복시킨다
B.3. 추가 변경점
for element in elements_list:
if len(element) != 4:
continue
title = element[1]
price = element[2].replace('%', '% 할인, ')
memo = element[3]
이 부분에서 거의 모든 에러가 났다고 볼 수 있는데,
수많은 시행착오 끝에 element의 길이는 4 또는 그보다 작은 경우의 수만 있다는 것을 확인했다
그래서 데이터를 긁을 현 element의 길이가 다를 경우 가차없이 continue로 돌려버려 현상을 해결했다
ex 에러 예시) [[]] , [ng Soon] 등
0. 전체 코드 / 실행 결과
# main.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
def get_page_count(keyword):
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
browser = webdriver.Chrome(options=options)
browser.get(f"https://www.kurly.com/search?sword={keyword}")
browser.implicitly_wait(time_to_wait=3)
pages = browser.find_element(By.XPATH, '//*[@id="container"]/div/div[2]/div[3]').text
# pages는 줄바꿈으로 이루어진 형태의 리스트이다
# 1\n2\n3\n4\n5\n6\n7\n8\n9\n10
pages = pages.splitlines()
count = []
# int형으로 모두 바꿔주고 최댓값 얻기
for page in pages:
count.append(int(page))
count = max(count)
# 10페이지 이상 넘어갈 수는 없으니 최대 10까지만 return한다
if count >= 10:
return 10
else:
return count
def extract_kurly_items(keyword):
# 화면에 띄워져 있는 페이지의 최대 수를 검색하기 위한 코드
pages = get_page_count(keyword)
print("Found", pages, "pages")
# 페이지 수 만큼 반복시키며 데이터를 가져오는 코드 실행
results = []
for page in range(1, pages+1):
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
browser = webdriver.Chrome(options=options)
url = 'https://www.kurly.com/search?sword='
final_url = f"{url}{keyword}&page={page}"
print("Requesting", final_url)
browser.get(final_url)
browser.implicitly_wait(time_to_wait=3)
elements = browser.find_element(By.XPATH, '//*[@id="container"]/div/div[2]/div[2]').text
items = elements.split('\n샛별배송')
items[0] = items[0][4:]
elements_list = []
for item in items:
items = item.splitlines()
elements_list.append(items)
# 뭔가 문제가 생기면 아래 코드를 실행해보면 답이 나온다
# print(elements_list)
for element in elements_list:
# 최대 고전 부분
# 현재 element 의 길이가 4가 아닌 경우 불량인 배열이므로 폐기
# 삭제 활용 시 리스트의 길이가 달라져서 실행 불가능
if len(element) != 4:
continue
title = element[1]
price = element[2].replace('%', '% 할인, ')
memo = element[3]
items_data = {
'상품명': title,
'가격': price,
'상품 설명': memo,
}
results.append(items_data)
return results
search = "상추"
ite = extract_kurly_items(search)
print(ite)
점점 무언가가 만들어지는 느낌이 든다
의미있는 결과물이 나왔으면 좋겠다
다음 편에서 계속됩니다