Beautiful Soup란?
Beautiful Soup은 웹페이지 분석 모듈로, HTML 코드에서 특정 태그나 값을 추출(parsing;파싱)할 때 사용하는 라이브러리입니다. requests 모듈로 HTML 소스를 받아오고 Beaitoful Soup은 이를 파싱합니다. parsing(파싱)이란 가공되지 않은 문자열에서 필요한 부분을 추출하여 의미있는 구조화된 데이터로 만드는 과정입니다.
[관련 문서]
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
설치방법
pip install bs4
티스토리 웹페이지 분석(기본)
# 모듈 가져오기
import requests
from bs4 import BeautifulSoup as bs
#웹사이트 소스 가져오기
res = requests.get('https://www.tistory.com/')
html = res.text
#html.parser를 이용하여 bs4 객체로 변환 후 웹페이지를 분석
soup = bs(html, 'html.parser')
데이터 추출
Beautiful Soup을 사용하여 웹페이지의 특정 태그를 가져오는 방법을 알아보겠습니다. find(), find_all(), select() 함수를 사용할 수 있습니다. 다양한 방법으로 실행해보기위해 html 코드를 그냥 막 만들어왔습니다. 사용할 html 코드는 다음과 같습니다.
import requests
from bs4 import BeautifulSoup as bs
#html 실습용 소스코드
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Beautiful Soup Ex</title>
</head>
<body>
<div class="tistory_info">
<h3>Tistroy</h3>
<p id="color1" class="tistory_color">티스토리는 오렌지색
<ul class="list1">
<li><a href="https://feed.com">피드</a></li>
<li><a href="https://story.com">스토리</a></li>
<li><a href="https://skin.com">스킨</a></li>
<li><a href="https://forum.com">포럼</a></li>
</ul>
<span class="life">라이프</span>
<span class="travel">여행</span>
<span class="it">IT</span>
<button id="ok" type="submit">ok</button>
</p>
</div>
<div class="naver_info">
<h3>Naver</h3>
<p id="color2" class="naver_color">네이버는 초록색
<ul class="list2">
<li><a href="https://mail.com">메일</a></li>
<li><a href="https://cafe.com">카페</a></li>
<li><a href="https://finance.com">증권</a></li>
</ul>
<span class="ytn">YTN</span>
<span class="mbc">mbc</span>
<span class="jtbc">jtbc</span>
<button id="cancel" type="submit">cancel</button>
</p>
</div>
</body>
</html>
'''
soup = bs(html, 'html.parser')
1. find() 함수
find()는 HTML 코드에서 원하는 태그를 가져올 수 있습니다. 동일한 태그가 여러 개 있을 경우 첫번째 태그 한 개만 가져옵니다.
print(soup.find('title'))
print(soup.find('li'))
#출력값
#<title>Beautiful Soup Ex</title>
#<li><a href="https://feed.com">피드</a></li>
HTML 코드를 보면 <span> 태그에서도 class속성이 각각 다른 것을 알 수 있습니다. span 태그를 속성값을 이용해서 가져올 수도 있습니다.
print(soup.find('span', class_='life'))
print(soup.find('span', class_='ytn'))
#출력값
#<span class="life">라이프</span>
#<span class="ytn">YTN</span>
2. find_all() 함수
find_all()은 동일한 태그가 여러 개인 경우 모두 가져옵니다.
print(soup.find_all('li'))
#'a' 출력값
'''
[<li><a href="https://feed.com">피드</a></li>, <li><a href="https://story.com">스토리</a></li>,
<li><a href="https://skin.com">스킨</a></li>, <li><a href="https://forum.com">포럼</a></li>,
<li><a href="https://mail.com">메일</a></li>, <li><a href="https://cafe.com">카페</a></li>,
<li><a href="https://finance.com">증권</a></li>]
'''
만약 두 개의 태그를 같이 찾고 싶다면 리스트로 묶어서 찾을 수 있습니다.
print(soup.find_all(['button','h3']))
#출력값
'''
[<h3>Tistroy</h3>, <button id="ok" type="submit">ok</button>,
<h3>Naver</h3>, <button id="cancel" type="submit">cancel</button>]
'''
3. select() 함수
select()는 다양한 옵션들을 가지고 있습니다.
#1. select('태그명')
print(soup.select('p'))
#2. select('태그명[속성]')
print(soup.select('a[href]'))
#인덱스 사용 가능
print(soup.select('a[href]')[0])
print(soup.select('a[href]')[5])
#3. select('.클래스명')
print(soup.select('.list1'))
#4. select('상위태그 > 하위태그 > 하위태그 > ...')
print(soup.select('div > p > ul > li'))
#인덱스 사용가능
print(soup.select('div > p > ul > li')[0])
print(soup.select('div > p > ul > li')[3])
#5.select('상위태그.클래스명' > '하위태그.클래스명')
print(soup.select('p.tistory_color > span.travel'))
#6. select('#id명')
print(soup.select('#ok'))
#7. select('#id명 > 태그명.클래스명')
print(soup.select('#color2 > ul.list2'))
4. 텍스트 추출
태그 내에 있는 텍스트를 추출하는 방법입니다. find()로 찾을 때는 하나만 추출하기 때문에 바로 print를 할 수 있지만, find_all()로 찾을 때는 모든 값을 찾기 때문에 for문을 사용해야합니다.
a = soup.find('a')
print(a.string) #피드
span = soup.find_all('span')
for i in span:
print(i.string)
#출력값
'''
라이프
여행
IT
YTN
mbc
jtbc
'''
#태그를 제외한 문자열 추출
print(soup.get_text()) #출력값은 길어서 생략