글 개요
파이썬에서 웹크롤링을 하려면 BeautifulSoup 와 Selenium 라이브러리를 사용해야 합니다. 그중 저는 BeautifulSoup라이브러리의 기초적인 문법을 정리하려고 합니다.
글 본문
BeautifulSoup()함수
from bs4 import BeautifulSoup
soup = BeautifulSoup(첫 번째 인자, 'html.parser')
print(soup.prettify())
BeautifulSoup함수의 첫 번째 인자는 크롤링 하고 싶은 사이트를 넣어주셔야 합니다. 그리고 prettify()함수는 html를 파이썬에서 정리된 모습으로 볼 수 있습니다.
from bs4 import BeautifulSoup
from urllib.request import urlopen
url = "https://finance.naver.com/marketindex/"
page = urlopen(url)
soup = BeautifulSoup(page, 'html.parser')
print(soup.prettify())
저는 네이버 금융 페이지에서 시장지표페이지를 간단한 크롤링을 해보려고 합니다.
제대로 실행이 된다면, 위 이미지처럼 네이버 금융 시장지표 페이지 정보를 가져오는걸 볼 수 있습니다.
html의 head 태그 body 태그 정보 가져오기
BeautifulSoup를 이용해서 html의 head정보를 가져올 수 있습니다.
from bs4 import beautifulSoup
soup = beautifulSoup(page, 'html.parser')
# html head태그 가져오기
soup.head()
# html body태그 가져오기
soup.body()
특정태그 찾기 find()함수
특정 사이트에서 우리가 원하는 정보만을 가져오려면 해당 정보의 태그를 잘 찾아서 가져와야 합니다. 정보를 가져오게 도와주는 find()함수가 있습니다.
from bs4 import beautifulSoup
soup = beautifulSoup(page, 'html.parser')
# 처음 발견한 p 태그를 가져온다.
soup.find('p')
# 모든 p 태그를 가져온다.
soup.find_all('p')
find()함수는 두 가지가 존재합니다. 단일 태그만 찾고자 할 때 find()함수를 사용하고, 모든 태그를 찾고자 할 때는 find_all()함수를 사용해서 태그를 찾으면 됩니다. find_all()함수는 결과를 리스트 형태로 반환됩니다.
find() 옵션인 class_, {key:vales}을 이용해서 자세하게 찾기
find()함수의 옵션을 활용하여 해당 정보를 자세하게 가져올 수 있습니다.
from bs4 import beautifulSoup
soup = beautifulSoup(page, 'html.parser')
soup.find('p', class_='inner-text first-item')
soup.find('p', class_='inner-text second-item')
soup.find('p', {'class':'inner-text first-item'})
soup.find('p', {'class': 'inner-text second-item'})
class_ 옵션을 이용해서 해당 정보를 가지고 있는 태그의 클래스 이름을 통해 가져올 수 있습니다. 또한, 딕셔너리 형태로도 가져올 수 있습니다.
태그 안에있는 text만 가져오는 함수
이제 태그 정보를 잘 가져왔다면 태그를 제거하고 태그 안에 있는 텍스트정보만 가져와야 할 때가 있습니다. 그때 사용하는 함수도 존재합니다.
<p ,="" class="inner-text first-item" id="first">
Happy
<a href="https://yoo-young.tistory.com/">Yoo 개발블로그</a>
</p>
#방법 1
print(soup.find('p').text)
#방법 2
print(soup.find('p').string)
#방법 3
print(soup.find('p').get_text())
#출력
'Yoo 개발블로그'
select_one(), select() 함수로 원하는 태그 찾기
위에서 find(), find_all()함수로 원하는 태그를 찾을 수 있다고 했습니다. beautifulsoup는 select_one()함수와 select()함수로도 원하는 태그를 찾을 수 있습니다.
단일 선택: find(), select_one()
다중 선택: find_all(), select()
하지만, select로 원하는 태그를 찾는 방법은 조금 다릅니다.
from bs4 import beautifulSoup
soup = beautifulSoup(page, 'html.parser')
soup.select('#exchangeList > li')
soup.select('.exchangeList > li')
앞에 #은 id값을 이용해서 찾을 때 사용하고 .은 class를 이용해서 찾을 때 사용합니다. 해석해보자면 exchangeList라는 아이디 안에 있는 li 태그를 다 가져와주세요.의미합니다.
실습
이제, 네이버 금융 시장조사 페이지에 있는 일부를 간단하게 크롤링을 하려고 합니다.
미국 USD 환율과 하락인지 상승인지 일본 환율도 하락인지 상승인지 유럽연합도 하락인지 상승인지를 크롤링을하고 데이터프레임으로 만들어 저장하는 실습을 해보겠습니다.
from bs4 import BeautifulSoup
from urllib.request import urlopen
url = "https://finance.naver.com/marketindex/"
page = urlopen(url)
soup = BeautifulSoup(page, 'html.parser')
exchangeList = select('#exchangeList > li')
select를 이용해서 태그정보를 가져오려면 ., #을 사용해야한다고 했습니다. id값이 exchangeList니 #exchangeList를 가져오라고 했고 그안에 있는 li태그들을 다 가져옵니다.
이렇게 결과들이 리스트로 반환되어 있는걸 확인할 수 있습니다. 이제 이 태그들 속에서 저희가 원하는 데이터들만 추출해야합니다.
이제 저희가 원하는 데이터는 이름, 환율, 변화정도, 상승 or 하락 데이터만 가져오면 됩니다. 그래서 리스트의 첫 번째 요소로 접근해서 정보를 가져오는 테스트를 시도해봅니다.
title = exchangeList[0].select_one(".h_lst").text
exchange = exchangeList[0].select_one('.value').text
change =exchangeList[0].select_one('.change').text
updown = exchangeList[0].select_one('.head_info.point_up > .blind').text
# 출력
('미국 USD', '1,184.40', '3.40', '상승')
여기서 조금 특이한 부분이 있습니다. updown변수는 상승과 하락정보를 가져오는 함수입니다. 이 태그는 조금 특이하게 생겼습니다.
chead_info point_dn 라는 클래스가 있는데 이 클래스 는 두개라는 소리입니다. 즉, head_info 클래스와 point_dn으로 두개로 되어있습니다. 그냥 띄어쓰기로 구분되어 있는게 아니라 두개로 구분되어 있는것입니다. 그래서 div class='head_info point_dn'를 가져오려면 .head_info.point_up .으로 이어서작성해야합니다.
이제 간단한 리스트의 첫 번째요소를 가져와서 테스트를 해보았으니, for문을 돌려서 4개의 국가의 환율정보를 가져옵시다.
# 4개 데이터 수집
exchange_data = []
baseurl = 'https://finance.naver.com/'
for item in exchangeList:
data = {
'title':item.select_one(".h_lst").text,
'exChange': item.select_one('.value').text,
"change" : item.select_one('.change').text,
"updown" : item.select_one('.head_info.point_up > .blind').text if item.select_one('.head_info.point_up > .blind') != None else item.select_one('.head_info.point_dn > .blind').text,
"link": baseurl + item.select_one('a').get('href')
}
print(data)
exchange_data.append(data)
이렇게 미국, 일본, 유럽연합, 중국의 환율정보를 가져올 수 있습니다. 상승과 하락의 변수인 updown변수는 삼항 조건 연산자를 사용해 데이터를 가져왔습니다. 왜냐하면 4개의 나라중 어떤 나라는 상승이고 어떤 나라는 하락인데 상승과 하락의 class 명이 달라지기 때문에 삼항 조건 연산자를 이용해서 데이터를 가져왔습니다.
이제 이 데이터들을 데이터프레임으로 만들고, 엑셀파일로 저장 하겠습니다.
import pandas as pd
df = pd.DataFrame(exchange_data)
df.to_excel('./naverfinance.xlsx', encoding='utf-8')
'Python Crawing' 카테고리의 다른 글
Selenium - headless 와 wait 문법 사용해보기 (0) | 2021.10.12 |
---|---|
Selenium - 기본 문법 이해하기 (3) | 2021.10.12 |
Selenium - iframe (0) | 2021.10.12 |
크롤링- 기초문법 활용 네이버 영화 평점 크롤링 (0) | 2021.10.05 |
댓글