python으로 크롤링(웹 스크래핑)을 할 때 beautiful soup은 굉장히 강력한 도구입니다.
하지만, 동적페이지 중 데이터를 따로 받아서 완성시키는 페이지들은 beautiful soup으로 가져오려고 하면 엉뚱한 데이터들이 가져와지거나 실패하는 경우가 종종 생깁니다.
물론 그런 페이지들도 beautiful soup을 집요하게 파고들면 스크랩이 가능한 것 같지만,
selenium을 이용하면 훨씬 간단하게 그런 페이지들을 스크래핑 할 수 있습니다.
selenium은 chrome을 이용해 실제 페이지를 띄우고 우리가 키보드 마우스로 하는 동작들을 자동화해주는 라이브러리입니다.
그럼 bs로 (쉽게) 가져올 수 없는 페이지 중에서
'네이버 증권 > 국내 증시 > 시가 총액' 페이지를 스크래핑해보도록 하겠습니다.
스크랩 할 부분
위 페이지에서 '종목명'과 '현재가'를 가져와 보도록 하겠습니다.
최종결과
위와 같은 결과가 나오도록 코딩을 해보겠습니다.
먼저 bs4를 이용해 스크랩하기 위해 페이지 구조를 살펴보도록 하겠습니다.
크롬 개발자 도구로 살펴 본 코드
먼저 종목명은 table 안에 두 번째 셀에 a태그 안에 들어있네요.
크롬 개발자도구
정확한 selector주소를 구하기 위해 크롬개발자 도구를 이용합니다.
#contentarea > div.box_type_l > table.type_2 > tbody > tr:nth-child(2) > td:nth-child(2) > a
이번 포스팅의 목적은 bs4 사용법이 아니기때문에 이후 과정은 생략하도록 하겠습니다.
이렇게 해서 bs4를 이용한 스크래핑 코드를 작성해보면
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://finance.naver.com/sise/sise_market_sum.nhn',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
stocks = soup.select('#contentarea > div.box_type_l > table.type_2 > tbody > tr')
for stock in stocks:
a_tag = stock.select_one('td:nth-child(2) > a')
if a_tag is not None:
price = stock.select_one('td:nth-child(3)').text
name = a_tag.text
row = {
'name': name,
'price': price
}
print(name, price)
위와 같이 작성할 수 있습니다. 그런데 스크립트를 실행시켜보면 제대로 작동하지 않습니다.
이제 여기서 selenium이 필요합니다.
기본적인 원리는 간단합니다. 우리는 이번에 selenium을 스크랩에만 이용할 것이기 때문에 간단하게 페이지가 로드된 후 html문서만 가져오는 것으로 selenium은 임무를 마치게 됩니다.
from selenium import webdriver
driver = webdriver.Chrome(executable_path="/Users/ssamko/Downloads/chromedriver")
url = 'https://finance.naver.com/sise/sise_market_sum.nhn'
driver.get(url)
soup = BeautifulSoup(driver.page_source, 'html.parser')
추가/변경할 코드는 위와 같습니다.
기존의 request로 page를 가져오던 것에서 selenium으로 page를 가져오는 것으로 바뀐 것 뿐, 나머지 bs4 코드는 그대로 사용하면 됩니다.
전체 코드는 아래와 같습니다.
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.Chrome(executable_path="/Users/ssamko/Downloads/chromedriver")
url = 'https://finance.naver.com/sise/sise_market_sum.nhn'
driver.get(url)
soup = BeautifulSoup(driver.page_source, 'html.parser')
stocks = soup.select('#contentarea > div.box_type_l > table.type_2 > tbody > tr')
for stock in stocks:
a_tag = stock.select_one('td:nth-child(2) > a')
if a_tag is not None:
price = stock.select_one('td:nth-child(3)').text
name = a_tag.text
row = {
'name': name,
'price': price
}
print(name, price)
driver.quit()
'자기계발' 카테고리의 다른 글
[Python pandas] excel 파일 읽기: read_excel() (0) | 2023.09.17 |
---|---|
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape (0) | 2023.09.17 |
Python pip 최신 버전 Upgrade 방법 (0) | 2023.09.10 |
독특한 채용 프로세스 사례 (1) | 2023.07.27 |
성공적인 회사 생활을 위한 팁 (0) | 2023.07.19 |