[Web] BeautifulSoup와 표현식

업데이트:

개요

png

이번 포스팅에서는 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의 자세한 함수 및 기능을 모르더라도, 정규표현식과 람다표현식만 잘 사용해도 원하는 결과를 충분히 얻을 수 있다.

댓글남기기