카테고리 없음

파이썬 활용 10 - 2 - 웹 스크래핑 (개요 및 패키지 활용)

H-V 2021. 12. 9. 12:03

 

 

  • 웹 스크래핑시에는 Python의 'BeautifulSoup' 라이브러리를 활용

 

 

01 HTML 파싱

  • BeautifulSoup을 사용하여 HTML문서를 파싱. 파싱 이후 태그를 끌어와서 스크래핑 가능
  • 파서 라이브러리는 4가지가 있는데 주로 'html.parser' or 'lxml' 을 많이 씀
  • HTML문서의 태그들에 접근시에는 <html>,<head>,<body>태그는 제외하고 접근하는게 좋음
  • 태그명 + '.' 연산자를 함께 사용

  • 태그들 간의 연관관계도 이해를 해야함
  • 간단 실습
from bs4 import BeautifulSoup

html_doc = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf
8">
<title>Test BeautifulSoup</title>
</head>
<body>
<h1>
테스트 </
</body>
</html> """


bs = BeautifulSoup(html_doc, 'html.parser')
print(type(bs)

<class 'bs4.BeautifulSoup'>
from bs4 import BeautifulSoup

html_doc = """
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Test BeautifulSoup</title>
</head>
<body>
<p align="center">P 태그의 컨텐트 </p>
<img src="http://unico2013.dothome.co.kr/image/flower.jpg" width="300">
</body>
</html> """

bs = BeautifulSoup(html_doc, 'html.parser')
print(bs.prettify())

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8"/>
  <title>
   Test BeautifulSoup
  </title>
 </head>
 <body>
  <h1>
   테스트
   <!--
</body-->
  </h1>
 </body>
</html>
html_doc = """
<!DOCTYPE html>
<html>
<head>
<meta charset='utf
8'>
<title>Test BeautifulSoup</title>
</head>
<body>
<p align="center">P 태그의 컨텐트 </p>
<img src="http://unico2013.dothome.co.kr/image/flower.jpg" width="300">
<ul>
<li>
테스트 1<strong> 강조 </strong></li>
<li>
테스트 2</li>
<li>
테스트 3</li>
</ul>
</body>
</html> """

bs = BeautifulSoup(html_doc, 'html.parser')
print(type(bs.title), ':', bs.title)
print(type(bs.title.name),':', bs.title.name)
print(type(bs.title.string),':', bs.title.string)
print('-------------------------------------------')
print(type(bs.p['align']),':', bs.p['align'])
print(type(bs.img['src']),':', bs.img['src'])
print(type(bs.img.attrs),':', bs.img.attrs)

print("[ string 속성 ]")
print(bs.p.string)
print(bs.ul.string)
print(bs.ul.li.string)
print(bs.ul.li.strong.string)

print("[ text 속성 ]")
print(bs.p.string)
print(bs.ul.text)
print(bs.ul.li.text)
print(bs.ul.li.strong.text)

print("[ contents 속성 ]")
print(bs.p.contents)
print(bs.ul.contents)
print(bs.ul.li.contents)
print(bs.ul.li.strong.contents)

 

 

02 웹상에서 파싱

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://stackoverflow.com")
bs = BeautifulSoup(html.read(), 'html.parser')

print(bs.title)
print()
print(bs.title.text)
print()
print(bs.h1)
print()
print(bs.h1.text)
print()
print(bs.span)

 

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = """
<html><body>
<h1>Hello python</h1>
<p>웹 페이지 분석 </p>
<p>웹 스크래핑 </p>
</body></html>
"""

soup = BeautifulSoup(html, 'html.parser')
h1 = soup.html.body.h1
p1 = soup.html.body.p
p2 = p1.next_sibling.next_sibling

print("h1=",h1)
print("h1=",h1.string)
print("p=",p1)
print("p=",p1.string)
print("p=",p2)
print("p=",p2.string)

h1= <h1>Hello python</h1>
h1= Hello python
p= <p>웹 페이지 분석 </p>
p= 웹 페이지 분석 
p= <p>웹 스크래핑 </p>
p= 웹 스크래핑
  1. 변수화(soup)를 통해 웹상의 HTML 내용을 담고 그 내용안에서 '.' 연산자를 이용하여 각각의 태그에 접근 가능
  2. 앞서 언급했듯이 각 태그의 연관성을 알면 반복되는 <p> 태그일지라도 접근이 가능
  3. 각 태그의 이름으로 불러오거나 태그들의 속성을 통해서도 불러 올 수 있다.

 

02 - 1 웹상에서의 파싱 2

  • BeautifulSoup의 라이브러리 중 강력한 기능들을 몇가지 알아 보자.
    find_all - 주어진 기준에 맞는 모든 태그들을 찾아 옴 *결과는 bs4.element.ResultSet 객체로 리턴
    find - 주어진 기준에 맞는 태그 한개를 찾아 옴 *결과는 bs4.element.Tag 객체로 리턴
    select - 주어진 CSS 선택자에 맞는 모든 태그를 찾아 옴 *결과는 list 객체로 리턴
  • HTML 문서는 트리구조 형식의 DOM형태인데 이 DOM형태들을 각각의 객체로 나누어서 속성으로 접근이 가능
  • 간단 실습
from urllib.request import urlopen
from bs4 import BeautifulSoup as bs

html = """
<html>
<body>
<h1 id="title">Hello python</h1>
<p id="body"> 웹 페이지 분석 </p>
<p> 웹 스크래핑 </p>
<span> 데이터 수집 1</span>
<span> 데이터 수집 2</span>
</body>
</html>
"""

soup = bs(html, 'html.parser')
title = soup.find(id='title')
body = soup.find(id='body')
span = soup.find('span')

print('#title = ', title)
print('#title = ' + title.string)
print('#body = ', body)
print('#body = ', body.string)
print('#span = ', span.string)

#title =  <h1 id="title">Hello python</h1>
#title = Hello python
#body =  <p id="body"> 웹 페이지 분석 </p>
#body =   웹 페이지 분석 
#span =   데이터 수집 1
  • 태그의 속성들이 없다면 위에서 하는 방법처럼 쉽게 찾을 수 있겠지만 보통 웹페이지는 그렇지 않다. 많은 HTML 내용과 CSS/JS 등으로 구성되어있기 때문에 태그의 속성으로 찾는것이 훨씬 편하다. 

 

from urllib.request import urlopen
from bs4 import BeautifulSoup as bs

html_doc = """
<!DOCTYPE html>
<html>
<head>
<meta charset='utf8'>
<title>Test BeautifulSoup</title>
</head>
<body>
<p align="center"> text contents </p>
<p align="right"> text contents 2 </p>
<p align="left"> text contents 3 </p>
<img src="http://unico2013.dothome.co.kr/image/flower.jpg" width="500">
<div>
<p>text contents 4</p>
</div>
</body>
</html> 
"""

bs = BeautifulSoup(html_doc, 'html.parser')

print(type(bs.find('p')))
print(type(bs.find_all('p')))
print("-----------------------------")
print(bs.find('title'))
print(bs.find('p')) # 가장 첫 번째 '<p>'를 들고 옴
print(bs.find('img'))
print("-----------------------------")
ptags = bs.find_all('p')
print(ptags)
print("-----------------------------")
for tag in ptags:
    print(tag)
    

<class 'bs4.element.Tag'>
<class 'bs4.element.ResultSet'>
-----------------------------
<title>Test BeautifulSoup</title>
<p align="center"> text contents </p>
<img src="http://unico2013.dothome.co.kr/image/flower.jpg" width="500"/>
-----------------------------
[<p align="center"> text contents </p>, 
<p align="right"> text contents 2 </p>,
<p align="left"> text contents 3 </p>, <p>text contents 4</p>]
-----------------------------
<p align="center"> text contents </p>
<p align="right"> text contents 2 </p>
<p align="left"> text contents 3 </p>
<p>text contents 4</p>