1. 程式人生 > >Python爬蟲包 BeautifulSoup 學習(八) parent等應用

Python爬蟲包 BeautifulSoup 學習(八) parent等應用

繼續使用上篇的html頁面內容:

html_doc = """ 
<html>
<head><title>The Dormouse's story</title></head> 
<p class="title"><b>The Dormouse's story</b></p> 
<p class="story">Once upon a time there were three little sisters; and their names were 
<a href="http://example.com/elsie"
class="sister" id="link1">
Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> </html
>
"""

繼續分析文件樹 ,每個 tag或字串都有父節點 :被包含在某個 tag中 。

.parent

通過 .parent 屬性來獲取某個元素的父節點。在例子html文件中,<head>標籤是<title>標籤的父節點:

title_tag = soup.title 
title_tag
# <title>The Dormouse's story</title> 
title_tag.parent 
# <head><title>The Dormouse's story</title></head>

title下的字串也有父節點:<title>標籤

title_tag.string.parent 
# <title>The Dormouse's story</title>

文件的頂層節點比如<html>的父節點是 BeautifulSoup 物件:

html_tag = soup.html 
type(html_tag.parent) 
# <class 'bs4.BeautifulSoup'>

BeautifulSoup 物件的 .parent 是None。

.parents

通過元素的.parents屬性可以遞迴得到元素的所有父輩節點 , 下面的例子使用了 .parents方法遍歷了<a>標籤到根節點 的所有節點:

link = soup.a 
link 
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
for parent in link.parents: 
    if parent is None: 
        print(parent) 
    else: 
        print(parent.name) 
# p 
# body 
# html 
# [document] 
# None

兄弟節點

舉例說明:

<a>
    <b>text1</b>
    <c>text2</c>
</a>

這裡的b和c節點為兄弟節點.

.next_sibling 和 .previous_sibling

在文件樹中,使用 .next_sibling 和 .previous_sibling 屬性來查詢兄弟節點:

sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></b></a>")
sibling_soup.b.next_sibling   
sibling_soup.c.previous_sibling 

# <c>text2</c> 
# <b>text1</b>

b 標籤有.next_sibling 屬性 ,但是沒有 .previous_sibling 屬性 ,因為 b標籤在同級節點中是第一個 。同理 ,c標籤有 .previous_sibling 屬性 ,卻沒有 .next_sibling 屬性 。

link = soup.a
link 
link.next_sibling 

# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
# u',\n'

注意:第一個a標籤的next_sibling 屬性值為,\n

link.next_sibling.next_sibling 
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>

第一個a標籤的next_sibling的next_sibling 屬性值為Lacie

.next_siblings 和 .previous_siblings

通過 .next_siblings 和 .previous_siblings 屬性對當前節點的兄弟節點迭代輸出:

for sibling in soup.a.next_siblings: 
    print(repr(sibling)) # u',\n' 

for sibling in soup.find(id="link3").previous_siblings:                                 print(repr(sibling)) 

# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> 
# u' and\n' 
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 
# u'; and they lived at the bottom of a well.' 
# None 


# ' and\n' 
# <a class="sister" 
# u',\n'
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
# u'Once upon a time there were three little sisters; and their names were\n' 
# None

回退和前進

舉例html如下:

<html><head><title>The Dormouse's story</title></head> <p class="title"><b>The Dormouse's story</b></p>

HTML 解析器把這段字串轉換成一連的事件 : “ 開啟標籤 ”新增一段字串 ”,關閉標籤 ”,”開啟標籤 ”, 等。

Beautiful Soup提供了重現解析器初始化過程的方法。

next_element 和 .previous_element

.next_element 屬性指向解析過程中下一個被的物件 (字串或 tag),結果可能 與 .next_sibling 相同 ,但通常是不一樣的。

last_a_tag = soup.find("a", id="link3") 
last_a_tag 
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 
last_a_tag.next_sibling 
# '; and they lived at the bottom of a well.'

但這個 <a>標籤的 .next_element 屬性結果是在標籤被解析之後的內容 ,不是<a>標籤後的句子部分 ,應該是字串 ”Tillie”:

last_a_tag.next_element 
# u'Tillie'

.previous_element 屬性剛好與.next_element 相反 ,它指向當前被解析的物件的前一個解析物件 :

last_a_tag.previous_element 
# u' and\n' 
last_a_tag.previous_element.next_element
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>

.next_elements 和 .previous_elements

通過 .next_elements 和 .previous_elements 的迭代器就可以向前或後訪問文件解析內容 ,就好像文件正在被解析一樣 :

for element in last_a_tag.next_elements:                  print(repr(element)) 
# u'Tillie' 
# u';\nand they lived at the bottom of a well.' 
# u'\n\n' 
# <p class="story">...</p> 
# u'...' 
# u'\n' 
# None