[Web] BeautifulSoup와 표현식
업데이트:
개요
이번 포스팅에서는 BeautifulSoup
라이브러리와 정규표현식, 람다(lambda)표현식 등을 활용하는 방법을 알아보자.
- 예제 url
- http://www.pythonscraping.com/pages/page3.html
1. 정규표현식활용
해당 페이지의 이미지 url을 수집하는 코드를 짠다고 가정해보자.
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bs = BeautifulSoup(html, 'html.parser')
bs.findAll('img')
[<img src="../img/gifts/logo.jpg" style="float:left;"/>,
<img src="../img/gifts/img1.jpg"/>,
<img src="../img/gifts/img2.jpg"/>,
<img src="../img/gifts/img3.jpg"/>,
<img src="../img/gifts/img4.jpg"/>,
<img src="../img/gifts/img6.jpg"/>]
단순히 findAll()
함수만을 이용한다면 해당 페이지의 모든 불필요한 이미지(로고 등)도 받아오게될 가능성이 크다.
따라서 표에 있는 이미지만을 추출하기 위해 정규표현식을 활용하면,
import re
bs.findAll('img', {'src':re.compile('\.\.\/img\/gifts/img.*\.jpg')})
[<img src="../img/gifts/img1.jpg"/>,
<img src="../img/gifts/img2.jpg"/>,
<img src="../img/gifts/img3.jpg"/>,
<img src="../img/gifts/img4.jpg"/>,
<img src="../img/gifts/img6.jpg"/>]
사실 위에서는 escape 문자 \
와 *
를 사용한 것외에는 복잡할 것도 없다.
중요한 건,
re.compile
을 통해 정규표현식으로 태그를 긁을 수 있다는 점
2. 속성에 바로 접근
href 속성에 들어 있는 url이나, src속성에 들어있는 image들을 바로 긁어 오고 싶을때가 있다.
예를들어
sometag = list(bs.find('td').next_siblings)[2]
sometag
<td>
<img src="../img/gifts/img1.jpg"/>
</td>
이 태그에서 img 태그의 src 속성에 들어있는 이미지 경로를 가져오고 싶다면.
sometag.img.attrs
{'src': '../img/gifts/img1.jpg'}
이렇게 접근할 수 있는데, 이 태그는 전형적인 파이썬 딕셔너리 객체이므로 src 속성을 선택하면 된다.
sometag.img['src']
'../img/gifts/img1.jpg'
3. 람다 표현식
람다함수는 파이썬 내장함수이다.
findAll
함수에 람다 함수를 사용하면, 태그 객체를 매개변수로 받아 boolean(True/False)를 반환하여 True로 평가된 태그를 출력해준다.
응용1 : 속성을 2개가진 태그만 반환
for i in bs.findAll(lambda tag : len(tag.attrs)==2):
print("="*10)
print(i)
==========
<img src="../img/gifts/logo.jpg" style="float:left;"/>
==========
<tr class="gift" id="gift1"><td>
Vegetable Basket
</td><td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
<span class="excitingNote">Now with super-colorful bell peppers!</span>
</td><td>
$15.00
</td><td>
<img src="../img/gifts/img1.jpg"/>
</td></tr>
==========
<tr class="gift" id="gift2"><td>
Russian Nesting Dolls
</td><td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"! <span class="excitingNote">8 entire dolls per set! Octuple the presents!</span>
</td><td>
$10,000.52
</td><td>
<img src="../img/gifts/img2.jpg"/>
</td></tr>
... 생략
즉, 웹 페이지의 모든 태그들을 검색하면서 속성을 2개 가진 태그를 반환하게 되는 것이다.
응용2 : 특정 텍스트를 포함한 태그만 반환
bs.findAll(lambda tag : tag.get_text() == 'Or maybe he\'s only resting?')
[<span class="excitingNote">Or maybe he's only resting?</span>]
람다 표현식을 사용하지 않고도 다음과 같이 쓸 수 있다.
bs.findAll('', text='Or maybe he\'s only resting?')
["Or maybe he's only resting?"]
이렇게 BeautifulSoup
의 자세한 함수 및 기능을 모르더라도, 정규표현식과 람다표현식만 잘 사용해도 원하는 결과를 충분히 얻을 수 있다.
댓글남기기