[Web Scrapping] BeautifulSoup 모듈
■ BeautifulSoup 모듈
- 문자열 추출방식은 각 페이지마다 다르게 개발된 웹 페이지에 적용하기 어렵다.
- 홈페이지 내 데이터를 쉽게 추출할 수 있도록 도와주는 파이썬 외부 라이브러리
- DOM Tree 형태로 구조화된 웹 페이지의 특정 요소를 이용하여 데이터를 추출하는 방법이 훨씬 유용
→ BeautifulSoup은 DOM Tree로부터 데이터를 추출해 올 수 있는 다양한 기능을 제공
■ BeautifulSoup을 이용한 데이터 추출 및 파싱
- BeautifulSoup 모듈과 외장 파서 등이 설치되어 있어야 한다.
■ Paser의 종류
종류 | 사용방법 | 특징 |
html.paser | BeautifulSoup(markup, "html.paser") BeautifulSoup('<a></p>', 'html.paser') → <a></a> 형태로 강제 변경되어 처리됨 |
- 파이썬이 제공하는 기본 파서 - 괜찮은 속도 |
lxml | BeautifulSoup(markup, "lxml") BeautifulSoup('<a></p>', 'lxml') → <html><body><a></a></body></html> 형태로 강제 변경되어 처리됨 |
- 기본값 - 아주 빠름 - 외부 C 라이브러리 의존 |
xml | BeautifulSoup(markup, "xml") BeautifulSoup('<a><b/>', 'xml') → <?xml version="1.0" encoding="utf-8" ?> |
- 아주 빠름 - XML 해석기 지원 |
html5lib | BeautifulSoup(markup, "html5lib") BeautifulSoup('<a><b />', 'html5lib') → <html><head></head><body><a><b></b></a></body></html> |
- 웹 브라우저와 동일한 방식으로 페이지를 분석하고 유효한 HTML5를 생성 - 매우 느림 |
■ BeautifulSoup을 이용한 데이터의 접근순서와 데이터 검색 방법
1) BeautifulSoup 모듈 import
from bs4 import BeautifulSoup
2) 태그를 이용한 접근
soup.title # soup 객체에서 첫 번째로 만나는 title 태그 출력
soup.footer.ul.li # soup 객체에서 첫 번째로 만나는 footer 태그의 하위 태그 ul, 그리고 그 하위 태그인 li 태그 출력
3) 태그와 속성을 이용한 접근
soup.a # soup 객체에서 첫 번째로 만나는 a element 출력
soup.a['id'] # a 태그의 속성들 중 "id" 속성값 정보 출력. 만약 속성이 존재하지 않을 경우 에러
4) find()를 이용한 태그 내의 다양한 속성을 이용한 접근
soup.find('a', attrs={'title':'구글봇'}) # a element의 속성 중 title 속성 값이 '구글봇'인 데이터 검색
soup.find(attrs={'title':'구글봇'}) # title 속성이 '구글봇'인 어떤 element를 찾아 검색
■ 웹 페이지 내에서 원하는 태그 찾기
- 웹 브러우저의 개발 툴 모드를 이용하여 원하는 데이터의 태그를 쉡게 검색할 수 있다.
1) 브라우저에서 F12를 눌러 개발자 모드 실행
2) 화살표 모양 클릭 후 찾고자 하는 부분 선택
■ 검색
○ 태그 : HTML의 해당 태그에 대한 첫 번째 정보를 가져옴
- 태그['속성'] : HTML 해당 태그의 속서에 대한 첫 번째 정보를 가져옴
import requests
from bs4 import BeautifulSoup
req = requests.get('https://www.naver.com')
html = req.text
soup = BeautifulSoup(html, 'html.parser')
print(soup.title) # <title>NAVER</title>
print(soup.title.name) # title
print(soup.title.string) # NAVER
○ find() : HTML의 해당 태그에 대한 첫 번재 정보를 가져옴
- find(속서='값') : HTML 해당 속성과 일치하는 값에 대한 첫 번째 정보를 가져옴
print(soup.find('a'))
print(soup.find(id='search'))
○ find_all() : HTML의 해당 태그에 대한 모든 정보를 리스트 형식으로 가져옴
- limit 옵션으로 개수 지정 가능
print(soup.find_all('a', limit=2))
- CSS 속성으로 필터링 (class_로 클래스를 직접 사용 혹은 attrs에서 속성=값으로 필터링)
result = soup.find_all('span', attrs={'class':'blind'})
print(len(result)) # 3개
print(result)
- string으로 검색 (해당 값이 있는지 없는지 검사할 때 활용, 정규 표현식과 함께 활용)
print(soup.find_all(string='자동완성 끄기'))
○ select_one(), select() : CSS 선택자를 활용하여 원하는 정보를 가져옴 (태그를 검색하는 find, find_all과 비슷함)
# 태그 찾기
soup.select('title')
# 특정 태그 아래에 있는 태그 찾기
soup.select('div a') # div 태그 아래에 있는 모든 a 태그 찾기
# 특정 태그 바로 아래에 있는 태그 찾기
soup.select('head > title')
soup.select('head > #link1') #id로 태그 찾음
# CSS class로 태그 찾기
soup.select('.sister')
# ID값으로 태그 찾기
soup.select('#link1')
■ CSS 선택자
- CSS에서 선택자는 스타일을 지정하려는 요소를 선택하는 데 사용되는 패턴이다.
- 주요 CSS 선택자
Selector | Example | Example Description |
.class | .intro | class="intro"를 갖는 모든 요소 선택 |
.calss1.class2 | .name1.name2 | 클래스 속성 내에서 name1과 name2가 모두 설정된 모든 요소를 선택 |
.class1 .class2 | .name1 .name2 | name1을 가진 요소의 하위 요소 중 name2를 가진 모든 요소를 선택 |
#id | #firstname | id="firstname"을 갖는 요소 선택 |
element | p | 모든 <p> 요소 선택 |
element.class | p.intro | class="intro"를 갖는 모든 <p> 요소 선택 |
element,element | div, p | 모든 <div> 요소와 모든 <p> 요소 선택 |
element element | div p | <div> 요소 내의 모든 <p> 요소 선택 |
element > element | div > p | 상위 요소가 <div> 요소인 모든 <p> 요소 선택 |
[attribute=value] | [target="_blank"] | target="_blank" 속성을 갖는 모든 요소 선택 |
"nth-child(n) | p:nth-child(2) | 부모 요소의 두 번째 자식 요소에 해당하는 모든 <p> 요소 선택 |
■ 태그 내의 문장 가져오기
● get_text() : 검색 결과에서 태그를 제외한 텍스트만 출력
text = soup.find('span', attrs={'class':'blind'})
print(text)
print(text.get_text())
● get('속성') : 해당 속성의 값을 출력
text = soup.find('span', attrs={'class':'blind'})
print(text)
print(text.get('class'))
● string : 검색 결과에서 태그 안에 또 다른 태그가 없는 경우 해당 내용을 출력. 태그 안에 또 다른 태그가 있는 경우에는 None을 반환
text = soup.find('a', attrs={'data-clk':'squ.dust'})
print(text)
print(text.string)
result = text.find('strong', attrs={'class':'state state_normal'}}
print(result.string)
● text : 검색 결과에서 하위 자식 태그의 텍스트까지 문자열로 반환
text = soup.find('a', attrs={'data-clk':'squ.dust'})
print(text)
print(result.text)