[WebCrawling] 웹사이트를 직접 분석해보자 -4편
Type: 데이터 수집 / 분석
주제: Web Crawling
사용 IDE: IntelliJ IDEA
사용 언어: Python
사용 패키지: selenium
GitHub Link: https://github.com/TMInstaller/WebCrawling_Myblog
설계 - 어떤 기능을 추가할까?
이번 편의 목표는 다음과 같다
목표1: 이전에 완성한 블로그 크롤러 함수화
목표2: 마켓컬리 크롤링을 해보자
이번 글에서는 지금까지 만들었던 블로그 크롤러를 함수화하고 다른 사이트의 검색창까지 크롤링해볼까 한다
그렇게 선택한 사이트는 마켓컬리이다
기존 작성해 두었던 블로그 크롤러는 함수화 시켜두었다
extracts forder - wwr.py
# wpc.py
# = web page crawling
from requests import get
from bs4 import BeautifulSoup
def extract_timemapexe_keys(keyword):
url = "https://time-map-installer.tistory.com/search/"
response = get(f"{url}{keyword}")
if response.status_code != 200:
print("페이지를 불러올 수 없습니다", response.status_code)
else:
results = []
soup = BeautifulSoup(response.text, 'html.parser')
keys = soup.find_all('div', class_='inner')
for key_section in keys:
key_posts = key_section.find_all('div', class_='post-item')
for post in key_posts:
span = post.find('a')
title = span.find('span', class_='title')
meta = span.find('span', class_='meta')
date = meta.find('span', class_='date')
excerpt = span.find('span', class_='excerpt')
key_data = {
'title': title.string,
'date': date.string,
'prev': excerpt.string
}
results.append(key_data)
return results
코드 작성
1. selenium을 이용해 웹사이트 접속 사전작업
2. 웹사이트 텍스트 정보 가져오기
3. 조건에 맞게 정리하기 위해 상품별 데이터 나누기
4. dict 생성 후 값 다듬고 저장하기
1. selenium을 이용해 웹사이트 접속 사전작업
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
아래에서 쓸 selenium 관련 함수를 미리 import 해주었고,
이 부분에 대해서는 강의의 내용을 참고했다
2. 웹사이트 텍스트 정보 가져오기
browser = webdriver.Chrome(options=options)
keyword = "고구마"
browser.get(f"https://www.kurly.com/search?sword={keyword}")
browser.implicitly_wait(time_to_wait=5)
elements = browser.find_element(By.XPATH, '//*[@id="container"]/div/div[2]/div[2]').text
이번에 검색해서 가져 올 조건은 고구마이다
마켓컬리의 정보를 얻어오는 데 굉장한 고구마를 먹었기 때문에
키워드도 고구마로 하였다
selenium을 이용해서 웹페이지의 정보를 가져오다가 대기시간이 없을 시
정보가 넘어오지 않는 경우가 있어 implicitly_wait를 이용해 대기시간을 주었다
이번에는 selenium이 가지고 있는 By와 XPATH를 이용해서 원하는 부분의 경로를
바로 텍스트로 얻어오는 방법을 택했다
3. 조건에 맞게 정리하기 위해 상품별 데이터 나누기
items = elements.split('\n샛별배송')
items[0] = items[0][4:]
elements_list = []
for item in items:
items = item.splitlines()
elements_list.append(items)
이 부분을 설계하는 데에 있어 가장 많은 시행착오를 겪었다
결과가 위와 같이 출력되게 하기 위한 작업이 생각보다 까다로웠던 것 같다
다행히 모든 상품 부분에 \n샛별배송이 붙어있어서 샛별배송을 기준으로
리스트를 나누는 아이디어를 내어 무사히 1번째 고비를 넘겼다
가장 처음에 오는 샛별배송 부분을 빼버리기 위해 슬라이싱으로 값을 변경하기도 했다
그리고 두 번째 고비인 1차원 배열을 2차원 배열로 만드는 작업에서도 굉장히 오래 헤멨던 것 같다
그러다가 상품이 달라질 때마다 줄이 바뀐 것을 확인하고
.splitlines() 을 이용하여 리스트 내의 리스트를 만들어 완성에 한걸음 더 나아갔다
4. dict 생성 후 값 다듬고 저장하기
results = []
for element in elements_list:
title = element[1]
price = element[2].replace('%', '% 할인, ')
memo = element[3]
items_data = {
'상품명': title,
'가격': price,
'상품 설명': memo,
}
results.append(items_data)
for result in results:
print(result, '\n')
리스트 자체를 for문으로 돌릴 때 생기는 편리한 기능 중 하나는
리스트의 index값이 자동으로 정해진다는 것인데, 아래와 같이 설정된다 보면 된다
element = elements_list[element][]
그렇게 데이터를 정리하고 가격 부분을 보다가 생긴 문제점이 있었다
저 할인 표시가 띄어쓰기 없이 그냥 넘어왔다는 점이다
그래서 위와같은 예외처리 작업을 해 두었다
0. 전체 코드 / 실행 결과
# main.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
# selenium을 이용하여 웹사이트의 정보를 얻어올 준비
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
# selenium을 이용하여 검색 했을 때의 결과 페이지 정보를 가져오기
browser = webdriver.Chrome(options=options)
keyword = "고구마"
browser.get(f"https://www.kurly.com/search?sword={keyword}")
# 5초의 대기 시간(페이지가 로딩 될 때까지 기다리는 역할)
browser.implicitly_wait(time_to_wait=5)
# XPATH를 이용하여 검색결과 아이템들의 텍스트 정보만 가져오기
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 = []
# 2차원 배열 안에 넣어두기
for item in items:
items = item.splitlines()
elements_list.append(items)
# 결과를 담을 results 배열 초기화
results = []
for element in elements_list:
# 상품명, 가격[변수 처리 작업], 상품 설명 설정
title = element[1]
price = element[2].replace('%', '% 할인, ')
memo = element[3]
# 설정한 변수들 dict type 으로 저장
items_data = {
'상품명': title,
'가격': price,
'상품 설명': memo,
}
results.append(items_data)
# 결과 출력
for result in results:
print(result, '\n')
다음 편에서 계속됩니다