본문 바로가기
Python/Python크롤링

DOM 구조 트리 이동

by hyun-am 2020. 9. 8.

DOM 구조 트리 이동

 

먼저 다음과 같은 홈페이지(http://www.pythonscraping.com/pages/page3.html)는 아래와 같은 HTML 트리 구조로 나타낼 수 있습니다.

 

  • html
    • body
      • div.wrapper
        • h1
        • div.content
        • table#giftList
          • tr
          • th
          • th
          • th
          • th
        • tr.gift#gift1
          • td
          • td
            • span.excitingNote
          • td
          • td
            • Img
        • 많은 테이블 행들
      • div.footer

 

자식과 자손

 

먼저 tr 태그는 table태그의 자식이며 tr과 th, td, img, span모두 table 태그의 자손입니다. 자식은 부모보다 한태그 아래있고 자손은 조상보다 몇 단계든 아래에 있을 수 있습니다.

또한 모든 자식은 자손이 될 수 있지만, 모든 자손은 자식이 아닙니다.

 

자식을 찾을 때

 

예를 들면 body태그의 자손인 첫번째 h1태그를 선택하려면 아래와 같은 코드를 입력하면 됩니다.

bsObj.body.h1

 

마찬가지로 문서의 첫번째 div 태그를 찾고 그 div 태그의 자손인 모든 img 태그 목록을 가져오고 싶으면 다음과 같이 사용하면 됩니다.

bsObj.div.findAll("img")

 

이제 위에 있는 예시 url을 이용하여 giftList 테이블에 있는 제품 행 목록을 출력하겠습니다.

.children 으로 관리합니다.

만약 자손까지 출력하고 싶으면

.descendants

를 입력하시면 됩니다.

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

html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = bs(html,"html.parser")

for child in bsObj.find("table",{"id":"giftList"}).children:
    print(child)

출력된 값은 다음과 같습니다.

<tr><th>
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>


<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>


<tr class="gift" id="gift3"><td>
Fish Painting
</td><td>
If something seems fishy about this painting, it's because it's a fish! <span class="excitingNote">Also hand-painted by trained monkeys!</span>
</td><td>
$10,005.00
</td><td>
<img src="../img/gifts/img3.jpg"/>
</td></tr>


<tr class="gift" id="gift4"><td>
Dead Parrot
</td><td>
This is an ex-parrot! <span class="excitingNote">Or maybe he's only resting?</span>
</td><td>
$0.50
</td><td>
<img src="../img/gifts/img4.jpg"/>
</td></tr>


<tr class="gift" id="gift5"><td>
Mystery Box
</td><td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining. <span class="excitingNote">Keep your friends guessing!</span>
</td><td>
$1.50
</td><td>
<img src="../img/gifts/img6.jpg"/>
</td></tr>

 

형제 다루기

 

BeautifulSoup에서 next_siblings( ) 함수를 이용하면 테이블에서 데이터를 쉽게 수집할 수 있으며, 특히 테이블에 타이틀 행이 있을때 유용합니다.

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

html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = bs(html,"html.parser")

for sibling in bsObj.find("table",{"id":"giftList"}).tr.next_siblings:
    print(sibling)

 

그러면 아래와 같이 th가 제외된 행들만 출력된 것을 확인할 수 있습니다.

<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>


<tr class="gift" id="gift3"><td>
Fish Painting
</td><td>
If something seems fishy about this painting, it's because it's a fish! <span class="excitingNote">Also hand-painted by trained monkeys!</span>
</td><td>
$10,005.00
</td><td>
<img src="../img/gifts/img3.jpg"/>
</td></tr>


<tr class="gift" id="gift4"><td>
Dead Parrot
</td><td>
This is an ex-parrot! <span class="excitingNote">Or maybe he's only resting?</span>
</td><td>
$0.50
</td><td>
<img src="../img/gifts/img4.jpg"/>
</td></tr>


<tr class="gift" id="gift5"><td>
Mystery Box
</td><td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining. <span class="excitingNote">Keep your friends guessing!</span>
</td><td>
$1.50
</td><td>
<img src="../img/gifts/img6.jpg"/>
</td></tr>

 

여기서 왜 th가 제거 됐을까요???

  1. 객체는 자기 자신의 형제가 될 수 없습니다.
  1. next_siblings()함수는 다음 형제들만 반환합니다.

 

⭐️ next_siblings를 보완하는 previous_siblings 함수도 있습니다. 이 함수는 원하는 형제 태그 목록의 마지막에 있는 태그를 쉽게 선택할 수 있을때 사용합니다.

 

부모 다루기

페이지를 스크래핑 하다보면 가끔 부모를 찾아야 할 때도 있습니다. 아래는 이미지가 나타내는 가격을 출력할 때 사용합니다. 다음과 같은 코드는 img1.jpg의 가격을 확인하고 싶을때 사용합니다.

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

html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = bs(html,"html.parser")

print(bsObj.find("img",{"src":"../img/gifts/img1.jpg"}).
    parent.previous_sibling.get_text())

# 출력값
# $15.00

 

댓글