goodthings4me.tistory.com
■ BeautifulSoup 활용 기초
O HTML과 XML 파일에서 데이터를 추출해내는 파이썬 라이브러리
O HTMl과 XML의 트리구조를 탐색, 검색, 변경 가능
O 다양한 파서(parser)를 선택하여 이용 가능
O 파서(parser)
-html.parser : 설치 필요 없음
-lxml : 실치 필요, 매우 빠름
-lxml-xml 또는 xml : 설치 필요, 매우 빠름
-html5lib : 설치 필요, 웹브라우저 방식으로 파싱(HTML5 생성), 매우 느림
O 활용
-BeautifulSoup(markup, 'html.parser')
-BeautifulSoup(markup, 'lxml')
-BeautifulSoup(markup, 'html.lxml-xml')
-BeautifulSoup(markup, 'html5lib')
example = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<h1>Heading 1</h1>
<p>Paragraph</p>
<div>
<a href="www.google.com">google</a>
</div>
<div class="class1">
<p>a</p>
<a href="www.naver.com">naver</a>
<p>b</p>
<p>c</p>
</div>
<div id="id1">
Example page
<p>g</p>
</div>
<h1>Footer</h1>
</body>
</html>
'''
soup = BeautifulSoup(example, 'html.parser')
print(soup.title)
# <title>Page Title</title> ## title 태그 내역
print(soup.title.name) ## title 태그 이름
# title
print(soup.title.string) ## title 태그의 문자열
# Page Title
print(soup.title.parent) ## title 태그를 포함하고 있는 태그의 내역
#<head>
#<meta charset="utf-8"/>
#<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
#<title>Page Title</title>
#</head>
print(soup.title.parent.name) ## 부모 태그 이름
# head
print(soup.h1) ## 첫 번째 h1 태그
# <h1>Heading 1</h1>
print(soup.p) ## 첫 번째 p 태그
# <p>Paragraph</p>
print(soup.div) ## 첫 번째 div 태그 내역
#<div>
#<a href="www.google.com">google</a>
#</div>
print(soup.a) ## 첫 번째 a 태그 내역
# <a href="www.google.com">google</a>
▷ HTML 태그 검색 - BeautifulSoup의 강력한 메서드
- find() : 해당 조건에 맞는 하나의 태그를 추출함
- find_all() : 해당 조건에 맞는 모든 태그를 추출함(ResultSet, list 형태)
- select() : "CSS 선택자와 같은 형식"으로 선택 가능(list 타입 반환)
## 상기 코드에 이어서
soup_find = soup.find('div') ## soup.div 와 동일
print(type(soup_find))
# <class 'bs4.element.Tag'>
print(soup_find) ## 첫 번째 div 태그 내역
# <div>
# <a href="www.google.com">google</a>
# </div>
soup_find_all = soup.find_all('div') ## div 태그 전체 추출 (list 형태)
print(type(soup_find_all))
# <class 'bs4.element.ResultSet'>
print(soup_find_all)
#[<div>
#<a href="www.google.com">google</a>
#</div>,
#<div class="class1">
#<p>a</p>
#<a href="www.naver.com">naver</a>
#<p>b</p>
#<p>c</p>
#</div>,
#<div id="id1">
# Example page
#<p>g</p>
#</div>]
print(type(soup_find_all))
# <class 'bs4.element.ResultSet'>
print(len(soup_find_all))
# 3
print(soup_find_all[1]) ## 리스트 index 1번째 요소 추출
#<div class="class1">
#<p>a</p>
#<a href="www.naver.com">naver</a>
#<p>b</p>
#<p>c</p>
#</div>
find_by_id = soup.find_all('div', {'id':'id1'}) ## 태그와 속성으로 추출(list 타입)
print(find_by_id)
#[<div id="id1">
# Example page
# <p>g</p>
#</div>]
find_by_class = soup.find_all('div', {'class':'class1'}) # class 속성으로 추출
print(find_by_class)
#[<div class="class1">
#<p>a</p>
#<a href="www.naver.com">naver</a>
#<p>b</p>
#<p>c</p>
#</div>]
print(soup.a)
# <a href="www.google.com">google</a>
print(soup.a.get('href')) ## a 태그의 href 속성 값 추출
# www.google.com
print(soup.a['href'])
# www.google.com
print(soup.a.text) ## a 태그의 문자열 추출
# google
print(soup.a.get_text())
# google
print(soup.find('a'))
# <a href="www.google.com">google</a>
print(soup.find('a').get('href'))
# www.google.com
print(soup.find('a')['href'])
# www.google.com
print(soup.find('a').text)
# google
print(soup.find('a').get_text())
# google
print(soup.find_all('a'))
# [<a href="www.google.com">google</a>, <a href="www.naver.com">naver</a>]
#print(soup.find_all('a').get('href')) # 에러
# AttributeError: ResultSet object has no attribute 'get'.
for a_tag in soup.find_all('a'): ## 각 요소별 속성 추출 위해 for문으로 순환
print(a_tag)
print(a_tag.get('href'))
print(a_tag.get_text())
#<a href="www.google.com">google</a>
#www.google.com
#google
#<a href="www.naver.com">naver</a>
#www.naver.com
#naver
for a_tag in soup.find_all('a'):
print(a_tag)
print(a_tag['href'])
print(a_tag.text)
#<a href="www.google.com">google</a>
#www.google.com
#google
#<a href="www.naver.com">naver</a>
#www.naver.com
#naver
## select는 지정 선택자의 모든 내역을 추출함 (list 타입 반환)
sel_id1 = soup.select('div#id1')
print(sel_id1) ## CSS 선택자 형식으로 추출 id는 #, class는 .
#[<div id="id1">
# Example page
# <p>g</p>
#</div>]
print(type(sel_id1))
# <class 'list'>
sel_class1 = soup.select('div.class1')
print(sel_class1)
#[<div class="class1">
#<p>a</p>
#<a href="www.naver.com">naver</a>
#<p>b</p>
#<p>c</p>
#</div>]
print(type(sel_class1))
# <class 'list'>
sel_h1 = soup.select('h1')
print(sel_h1)
# [<h1>Heading 1</h1>, <h1>Footer</h1>]
print(type(sel_h1))
# <class 'list'>
class1_a = soup.select('div.class1 a') ## class1 태그 내 a 태그 추출 (list)
print(class1_a)
# [<a href="www.naver.com">naver</a>]
print(type(class1_a))
# <class 'list'>
print(class1_a[0].get('href')) ## list 내 index로 접근하여 href 속성 값 추출
# www.naver.com
▷ 다른 예제
national_anthem = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>애국가</title>
</head>
<body>
<div>
<p id="title">애국가</p>
<p class="content">
동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라 만세.<br />
무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.<br />
</p>
<p class="content">
남산 위에 저 소나무 철갑을 두른 듯 바람서리 불변함은 우리 기상일세.<br />
무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.<br />
</p>
<p class="content">
가을 하늘 공활한데 높고 구름 없이 밝은 달은 우리 가슴 일편단심일세.<br />
무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.<br />
</p>
<p class="content">
이 기상과 이 맘으로 충성을 다하여 괴로우나 즐거우나 나라 사랑하세.<br />
무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.<br />
</p>
</div>
</body>
</html>
'''
soup = BeautifulSoup(national_anthem, 'html.parser')
print(soup.find('p', id = 'title').text)
## soup.find('p', {'id' = 'title'}).text 또는 soup.title.text 와 동일
# 애국가
contents = soup.select('p.content') ## p 태그 class 속성값
for p_tag in contents:
print(p_tag.get_text())
[실행 결과]
#
#동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라 만세.
#무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.
#
#
#남산 위에 저 소나무 철갑을 두른 듯 바람서리 불변함은 우리 기상일세.
#무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.
#
#
#가을 하늘 공활한데 높고 구름 없이 밝은 달은 우리 가슴 일편단심일세.
#무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세.
#
#
#이 기상과 이 맘으로 충성을 다하여 괴로우나 즐거우나 나라 사랑하세.
#무궁화 삼천리 화려 강산 대한 사람 대한으로 길이 보전하세
#
▷ 인터넷 웹페이지 가져오기
url = 'http://suanlab.com/'
html = urllib.request.urlopen(url)
print(html)
# <http.client.HTTPResponse object at 0x000001914842F978>
html = html.read()
soup = BeautifulSoup(html, 'html.parser')
#print(soup)
labels = soup.find_all('label')
for label in labels:
print(label.get_text())
[실행 결과]
#[2020-05-20] "인공지능의 보안 위협" 칼럼
#[2020-03-04] "데이터 경제 시대" 칼럼
#[2019-12-25] "마이데이터 시대의 도래 데이터 주권과 새로운 가치" 칼럼
#[2019-09-25] "유튜브 탄생과 크리에이터 시대" 칼럼
#[2019-09-04] "농업으로 들어간 인공지능" 칼럼
#[2019-08-07] "AI시대 지배할 것인가 지배당하며 살 것인가" 칼럼
#[2018-12-30] "파이썬으로 텍스트 분석하기" 책 출판
labels = soup.select('#wrapper > section > div > div > div > div > div > label')
## label에서 마우스 우클릭 후 Copy>>Copy selector
for label in labels:
print(label.get_text())
[실행 결과]
#[2020-05-20] "인공지능의 보안 위협" 칼럼
#[2020-03-04] "데이터 경제 시대" 칼럼
#[2019-12-25] "마이데이터 시대의 도래 데이터 주권과 새로운 가치" 칼럼
#[2019-09-25] "유튜브 탄생과 크리에이터 시대" 칼럼
#[2019-09-04] "농업으로 들어간 인공지능" 칼럼
#[2019-08-07] "AI시대 지배할 것인가 지배당하며 살 것인가" 칼럼
#[2018-12-30] "파이썬으로 텍스트 분석하기" 책 출판
▷ 전 세계 웹사이트 순위 스크래핑
from bs4 import BeautifulSoup
import urllib.request
import pandas as pd
url = 'https://www.alexa.com/topsites'
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')
sites = soup.find_all('div', {'class':'tr site-listing'})
for site in sites:
rank = site.find('div', class_ = 'td').get_text()
website = site.select('p > a')[0].get_text()
infos = site.find_all('div', {'class':'td right'})
time = infos[0].get_text()
pageview = infos[1].get_text()
traffic = infos[2].get_text()
linking = infos[3].get_text()
print(rank, website, time, pageview, traffic, linking)
[실행 결과]
1 Google.com 15:25 16.71 0.40% 1,322,590
2 Youtube.com 16:36 9.20 15.00% 1,007,247
3 Tmall.com 7:02 3.77 0.90% 6,224
4 Facebook.com 18:52 8.75 8.60% 2,237,169
5 Baidu.com 9:05 4.55 5.10% 104,502
6 Qq.com 3:38 3.92 2.90% 269,115
7 Sohu.com 3:40 4.61 1.70% 27,065
8 Taobao.com 4:37 3.59 3.30% 25,542
9 360.cn 3:14 4.11 0.40% 15,582
10 Jd.com 3:30 4.39 1.40% 8,785
11 Amazon.com 10:10 9.47 19.70% 368,084
12 Yahoo.com 4:53 4.56 7.90% 323,499
13 Wikipedia.org 3:45 3.02 74.10% 773,868
14 Zoom.us 8:41 3.96 13.40% 3,076
15 Weibo.com 2:58 3.65 2.10% 71,025
16 Sina.com.cn 2:51 3.41 2.50% 46,925
17 Live.com 5:21 5.32 10.40% 42,943
18 Reddit.com 5:31 4.34 30.90% 168,183
19 Netflix.com 4:17 3.19 9.40% 11,000
20 Xinhuanet.com 2:54 5.58 2.50% 34,834
21 Microsoft.com 4:36 3.38 25.80% 240,212
22 Okezone.com 4:00 4.14 7.40% 10,516
23 Vk.com 7:16 3.82 9.30% 127,024
24 Office.com 9:50 9.23 7.00% 5,887
25 Instagram.com 8:45 9.56 13.70% 639,719
26 Csdn.net 3:18 4.93 7.20% 6,556
27 Alipay.com 2:53 3.19 1.40% 3,592
28 Microsoftonline.com 1:14 1.92 2.70% 702
29 Myshopify.com 21:41 14.57 3.10% 128
30 Yahoo.co.jp 8:47 8.21 13.80% 58,916
31 Panda.tv 2:47 5.33 0.80% 372
32 Zhanqi.tv 2:51 5.42 0.80% 352
33 Twitch.tv 6:34 3.41 6.70% 10,022
34 Bongacams.com 2:57 1.62 6.80% 167,978
35 Google.com.hk 3:50 5.37 3.40% 9,726
36 Amazon.in 13:36 11.29 25.80% 6,854
37 Naver.com 14:11 11.20 10.10% 39,418
38 Bing.com 2:46 2.65 6.10% 42,641
39 Apple.com 3:54 3.86 37.50% 178,218
40 Ebay.com 10:01 7.90 16.40% 75,866
41 Aliexpress.com 11:02 9.45 14.80% 19,325
42 Tianya.cn 2:49 5.07 0.90% 5,331
43 Amazon.co.jp 7:45 9.24 17.50% 50,006
44 Stackoverflow.com 6:09 3.87 74.90% 26,660
45 Google.co.in 6:30 12.19 10.00% 17,539
46 Adobe.com 3:57 3.77 24.80% 248,973
47 Livejasmin.com 2:33 1.76 3.20% 11,354
48 Twitter.com 12:57 10.17 11.50% 1,622,153
49 Yandex.ru 6:08 3.82 2.90% 95,164
50 Tribunnews.com 3:40 1.92 61.80% 23,839
[참고] 이수안컴퓨터연구소
'코딩 연습 > 코딩배우기' 카테고리의 다른 글
파이썬 크롤링(Crawling) 연습 - BeautifulSoup Documentation #1 (html 태그로 접근, 객체 4종류 등) (0) | 2020.11.07 |
---|---|
파이썬 크롤링(Crawling) 연습 - 네이버 영화 평점/리뷰, 영화코드 추출 (0) | 2020.11.04 |
파이썬 크롤링(Crawling) 연습 - Daum에서 검색한 전화번호의 기본 정보 추출 (0) | 2020.11.01 |
파이썬 크롤링(Crawling) 연습 - find(), find_all() 사용한 네이버 증시 주가 추출 (0) | 2020.10.29 |
파이썬 크롤링(Crawling) 연습 - BeautifulSoup 객체를 모듈로 만들어서 사용해보기 (0) | 2020.10.27 |
댓글