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 BeautifulSoupsoup = 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 contents3.跨級獲取子節點
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))去除空白字元
6.父節點
每個節點都有自己的父節點。除了第一個
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, "lxml")
title_tag = soup.titleprint(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.htmlprint(type(html_tag.parent))print(5.-------------------)# BeautifulSoup 對象的 .parent 是None:print(soup.parent)遍歷所有父節點:
soup = BeautifulSoup(html_doc, "lxml")
link = soup.afor 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語言實戰第三關筆記和實踐
※入場比特幣堪比大冒險?他用一千多種交易數據給你定心丸
※扯個關於大數據的淡