Search

BeautifulSoup

설치

pip 또는 anaconda 를 활용해서 다운로드하면 된다.
터미널을 키고
conda install -c anaconda beautifulsoup4 # 또는 pip install beautifulsoup4
Python
복사

기초 문법

다음과 같은 순서로 문법이 활용된다.
< !DOCTYPE html> : html 을 사용할 것이라고 명령
<html>
<head>
<title>
</head>
<body>
<div>
<p>
<a></a>
</p>
</div>
</body>
</html>
<!DOCTYPE html> <html> <head> <title>Very Simple HTML Code by Jumee</title> </head> <body> <div> <p class="inner-text first-item" id="first"> Happy Jumee. <a href="http://www.pinkwink.kr" target='_blink' id="pw-link">PinkWink</a> </p> <p class="inner-text second-item"> Happy Data Science. <a href="https://www.python.org" target='_blink' id="py-link">Python</a> </p> </div> <p class="outer-text first-item" id="second"> <b>Data Science is funny.</b> </p> <p class="outer-text"> <i>All I need is Love.</i> </p> </body> </html>
HTML
복사
head :
웹 페이지를 열었을 때, 보통 창에 나오는 페이지의 제목(이름)을 구성해준다.
body
페이지 본문의 내용을 담는 부분을 알려주는 곳이다.
p
paragraph 의 약자. 문단의 시작을 의미한다.
본문에 표현할 내용을 담으면 되고, <a href> 와 같이 링크를 포함할 수도 있다.
 target=’_blink’ 의 의미
링크를 클릭했을 때, 새 창에서 보여주는 기능이다.

Basic

html 데이터 읽어들이기

BeautifulSoup 함수 이용하기
from bs4 import BeautifulSoup # 읽어들일 html 파일이 있다면 page = open('../data/ZeroBase.html','r').read() soup = BeautifulSoup(page, 'html.parser') # 해당 페이지를 읽는데, 엔진을 html.parser 로 설정한다. # 불러들일 때, indent 가 들어가 있는 상태에서 읽어들이기 print(soup.prettify())
Python
복사
각각의 태그 내용을 확인하기
# head 내용 확인 soup.head # p 태그 확인 - 태그 중 맨 첫번째것만 확인한다. soup.p # body 태그 확인 soup.body
Python
복사
조건을 세부적으로 설정해서 원하는 태그 내용 가져오기
find()
# p 태그에서 class 가 'inner-text second-item' 인 태그 속성만 가져오기 soup.find('p', class_='inner-text second-item')
Python
복사
# 딕셔너리도 사용 가능 soup.find('p', {'class':'outer-text first-item'})
Python
복사
find() 의 결과 내용에서 text 만 추출하기
soup.find('p', {'class':'outer-text first-item'}).text # 개행 문자 없이 추출하려면 soup.find('p', {'class':'outer-text first-item'}).text.strip()
Python
복사
딕셔너리로 다중 조건 설정해서 추출하기
# class 조건, id 조건 설정해서 추출 soup.find('p', {'class':'outer-text first-item', 'id':'second'})
Python
복사
find_all() : 조건에 맞는 여러 태그를 반환, 리스트 형태로 반환함에 유의
# p 태그 모두 추출 soup.find_all('p')
Python
복사
# 모든 p 태그 중, class가 'outer-text'를 포함하는 태그만 추출 soup.find_all(class_='outer-text')
Python
복사
# id 가 'pw-link'인 태그만 추출 soup.find_all(id='pw-link')
Python
복사
find_all 결과물에서 text 만 추출하기 : 리스트라는 점에 유의
# id 가 'pw-link'인 태그에서 텍스트만 추출 soup.find_all(id='pw-link')[0].text # 또는 soup.find_all(id='pw-link')[0].get_text()
Python
복사
이를 응용해서
# 모든 p태그 속성에서 텍스트만 추출하기 for each_tag in soup.find_all('p'): print('-'*50) print(each_tag.text)
Python
복사
# a 태그에서 href 속성값에 있는 링크 값과 텍스트 값을 활용해보기 for each_link in soup.find_all('a'): href = each_link.get('href') # each_link['href'] text = each_link.get_text() print(text + '=>' + href)
Python
복사

실제 웹페이지 읽어들이기

네이버 증시 시장 지표 페이지 : https://finance.naver.com/marketindex/
위의 페이지에서 미국 환율 지표를 가져오려고 한다.
요렇게, span 태그의 class 속성을 사용한다면 가져올 수 있다.
urllib.request 패키지에서 urlopen 함수로 페이지 요청하고 읽어들이기
from urllib.request import urlopen url = ' https://finance.naver.com/marketindex/' page = urlopen(url) # 페이지를 요청 soup = BeautifulSoup(page, 'html.parser') # 해당 페이지를 읽어들이기 print(soup.prettify())
Python
복사
태그의 환율 값 불러들이기(세가지 방식)
# 1. soup.find_all('span','value') # 2. soup.find_all('span', class_='value') # 3. soup.find_all('span', {'class':'value'})
Python
복사
# 미국 환율값(text) 불러오기(세가지 방식) soup.find_all('span',{'class':'value'})[0].string # text, get_text()
Python
복사
 HTTP 상태 코드
웹페이지를 불러들였을 때, 정상적으로 요청하고 불러들인 것인지 확인해야 될 필요가 있다.
더 자세한 HTTP 상태 코드 링크는 아래를 참고하자.
url = ' https://finance.naver.com/marketindex/' page = urlopen(url) # 페이지를 요청하고 받았다면 page.status # 페이지 상태 확인해보기
Python
복사
requests 패키지 사용하기
앞서, urllib.request 와 기능은 같지만, 자주 사용되는 다른 패키지다.
다운로드
pip3 install requests
Python
복사
import
import requests # urllib.request.Request 와 동일 기능
Python
복사
url 요청하고 html 데이터 받기
url = 'https://finance.naver.com/marketindex/' response = requests.get(url) response
Python
복사
BeautifulSoup 사용해서 데이터 읽어오기
soup = BeautifulSoup(response.text, 'html.parser') print(soup.prettify())
Python
복사
앞선 urllib 과 다르게 .text 를 붙여줘야 읽어온다.
태그 읽어오기
id : 태그 내에 유일하게 존재할 수 있는 값이다.
id : 이름 앞에 ‘#’ 을 붙여서 상위를 의미한다.
class : class 이름은 유일하지 않기 때문에 상위 속성을 잘 명시해줘야 한다.
class : 이름 앞에 ‘ . ’ 을 붙여서 상위를 의미한다.
select : 다중 선택(= find_all)
select_one : 단일 선택(=find)
# id가 exchangeList 인 하위 태그 안에 li 태그들은 모두 다 가져온다. exchangeList = soup.select('#exchangeList > li') # > 는 '하위' 를 의미한다. len(exchangeList), exchangeList
Python
복사
# '제목, 환율값, 변동율, 상승/하락 여부' 가 담긴 데이터만 추출하자 # 미국과 관련된 title = exchangeList[0].select_one(".h_lst").text exchange = exchangeList[0].select_one(".value").text change = exchangeList[0].select_one(".change").text # blind 속성은 앞에도 있기 떄문에, 상위 속성을 더 명시해줘야 한다. # 참고로 속성에 띄어쓰기가 의미하는 것은 속성값이 여러 개라는 것을 말한다. # > 가 있고 없고의 차이를 잘 구분하자! updown = exchangeList[0].select_one(".head_info.point_up > .blind").text url = exchangeList[0].select_one("a").get("href") title, exchange, change, updown, url
Python
복사
# url의 경우, 앞의 'https://finance.naver.com' 이 없기때문에 제대로 웹페이지가 열리지 않는다. # 수동으로 위의 페이지 경로를 붙여줘야 한다. baseUrl = 'https://finance.naver.com' url = baseUrl + url
Python
복사
추출한 데이터 테이터 프레임으로 변환하기
# 미국, 일본, 유럽연합, 중국 -> 4개의 데이터를 추출해서 데이터프레임으로 만들자. exchange_datas = [] 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, "link" : url } exchange_datas.append(data) exchange_datas
Python
복사
# 리스트 안 딕셔너리 -> 데이터프레임 변환 df = pd.DataFrame(exchange_datas)
Python
복사
# excel파일로 저장 df.to_excel('./naverfinance.xlsx', encoding='utf-8')
Python
복사
한꺼번에 파이썬 파일로 데이터 크롤링 + 데이터프레임 변환 + 엑셀 저장까지
# naver.py import requests import pandas as pd # from urllib.request.Request from bs4 import BeautifulSoup url = 'https://finance.naver.com/marketindex/' response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') exchangeList = soup.select('#exchangeList > li') # > 는 '하위' 를 의미한다. exchange_datas = [] 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, "link" : baseUrl + item.select_one("a").get('href') } exchange_datas.append(data) df = pd.DataFrame(exchange_datas) df.to_excel('./naverfinance.xlsx', encoding='utf-8')
Python
복사