-
파이썬 크롤링(Crawling) 연습 - BeautifulSoup 활용 기초코딩 연습/코딩배우기 2020. 11. 3. 21:43
■ 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