Python爬蟲系列(五):分析HTML結構

今晚,被煩死了。9點多才下班,就想回來看書學習,結果被嘮叨嘮叨個小時,我不斷喊不要和我聊天了,還反覆說。我只想安安靜靜看看書,學習學習,全世界都不要打擾我

接著上一個討論,我們今晚要分析HTML結構了

1.獲取元素

html_doc = """

<html>

<head>

<title>The Dormouses story

</title>

</head>

<p class="title"><b>The Dormouses 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>

"""

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

# 直接訪問head元素

print(soup.head)

# 多個a元素只會返回第一個

print(soup.a)

# 通過層級獲取 注意:上面沒有body,soup會自動補全

print(soup.body.p)

# 獲取所有a,返回a的數組

print(soup.find_all(a))

2.獲取內容和子元素

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

head_tag = soup.head

# 通過列表輸出文檔元素

print(head_tag.contents)

title_tag = head_tag.contents[1]

print(---------------------------)

print(title_tag)

print(---------------------------)

print(title_tag.contents)

print(---------------------------)

# BeautifulSoup 對象本身一定會包含子節點,也就是說<html>標籤也是 BeautifulSoup 對象的子節點:

print(len(soup.contents))

print(soup.contents[0].name)

print(---------------------------)

# 通過tag的 .children 生成器,可以對tag的子節點進行循環

#title_tag.children是<title>The Dormouses story</title>

for child in title_tag.children:

print(child)

# 字元串沒有 .contents 屬性,因為字元串沒有子節點:

print(---------------------------)

text = title_tag.contents[0]

print(text.contents) #直接報錯 :AttributeError: NavigableString object has no attribute contents

3.跨級獲取子節點

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

head_tag = soup.head

# 遞歸獲取所有子節點

for child in head_tag.descendants:

print(-----------------------)

print(child)

# 直接子節點

print(len(list(soup.children)))

# 跨級子節點:包括換行符 都算成了子節點。在使用的過程中,一定要注意判空

print(len(list(soup.descendants)))

4.string字元串

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

head_tag = soup.head

# title_tag.string是title標籤的子節點。即便是純粹的string 這個就是 NavigableString

# print(title_tag.string)

# 如果一個tag僅有一個子節點,那麼這個tag也可以使用 .string 方法,輸出結果與當前唯一子節點的 .string 結果相同:

print(head_tag.contents)

# 如果tag包含了多個子節點,tag就無法確定 .string 方法應該調用哪個子節點的內容, .string 的輸出結果是 None :

print(soup.html.string)

5.遍歷字元串和去除空白字元

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

# 如果tag中包含多個字元串 [2] ,可以使用 .strings 來循環獲取:

# for string in soup.strings:

# print(repr(string))

# 輸出的字元串中可能包含了很多空格或空行, 使用.stripped_strings

# 可以去除多餘空白內容:

for string in soup.stripped_strings:

print(repr(string))

去除空白字元

6.父節點

每個節點都有自己的父節點。除了第一個

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_doc, "lxml")

title_tag = soup.title

print(1.-------------------)

print(title_tag)

print(2.-------------------)

print(title_tag.parent)

print(3.-------------------)

# 文檔title的字元串也有父節點:<title>標籤

print(title_tag.string.parent)

print(4.-------------------)

# 文檔的頂層節點比如<html>的父節點是 BeautifulSoup 對象:

html_tag = soup.html

print(type(html_tag.parent))

print(5.-------------------)

# BeautifulSoup 對象的 .parent 是None:

print(soup.parent)

遍歷所有父節點:

soup = BeautifulSoup(html_doc, "lxml")

link = soup.a

for parent in link.parents:

if parent is None:

print(parent)

else:

print(parent.name)

7.兄弟節點

同一個級別的節點查找

sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></b></a>", "lxml")

# b後面一個兄弟節點

print(sibling_soup.b.next_sibling)

# c前面一個兄弟節點

print(sibling_soup.c.previous_sibling)

# 同一節點沒有前一個

print(sibling_soup.b.previous_sibling)

# 同一節點沒有最後一個

print(sibling_soup.c.next_sibling)

獲取前後所有的兄弟節點

注意:這些節點包括字元串和符號

soup = BeautifulSoup(html_doc, "lxml")

for sibling in soup.a.next_siblings:

print(--------------------------)

print(repr(sibling))

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

print(******************************)

print(repr(sibling))

8.回退和前進

注意看next_sibling和next_element的差別

soup = BeautifulSoup(html_doc, "lxml")

last_a_tag = soup.find("a", id="link3")

# 是指link3之後的內容

print(last_a_tag.next_sibling)

print(----------------------)

# 是指link3內部之後的內容

print(last_a_tag.next_element)

print(last_a_tag.next_element.next_element)

soup = BeautifulSoup(html_doc, "lxml")

last_a_tag = soup.find("a", id="link3")

#next_elements和previous_elements 會訪問當前節點內部往後和外部往後的所有內容。內部往後優先

for element in last_a_tag.next_elements:

print(repr(element))

還有一節,培訓新手的文檔就結束了。真心希望同學們要好好學習,不然我白講。 不下班回家陪我的小公舉,卻來義務教你寫代碼,而且是從零開始手把手教。兄弟們要加油啊


推薦閱讀:

【線上直播】數據很重要,Storm幫你現在就要
鹿豹座平台(1.8-1.12)大數據新聞每周精選
R語言實戰第三關筆記和實踐
入場比特幣堪比大冒險?他用一千多種交易數據給你定心丸
扯個關於大數據的淡

TAG:爬蟲 | 大數據 | Python |