天天看點

第65天:爬蟲利器 Beautiful Soup 之周遊文檔

by 豆豆

Beautiful Soup 是一個可以從 HTML 或 XML 檔案中提取資料的 Python 庫,它提供了一些簡單的操作方式來幫助你處理文檔導航,查找,修改文檔等繁瑣的工作。因為使用簡單,是以 Beautiful Soup 會幫你節省不少的工作時間。

你可以使用如下指令安裝 Beautiful Soup。二選一即可。

Beautiful Soup 不僅支援 Python 标準庫中的 HTML 解析器,還支援很多第三方的解析器,比如 lxml,html5lib 等。初始化 Beautiful Soup 對象時如果不指定解析器,那麼 Beautiful Soup 将會選擇最合适的解析器(前提是你的機器安裝了該解析器)來解析文檔,當然你也可以手動指定解析器。這裡推薦大家使用 lxml 解析器,功能強大,友善快捷,而且該解析器是唯一支援 XML 的解析器。

你可以使用如下指令來安裝 lxml 解析器。二選一即可。

Beautiful Soup 使用來起來非常簡單,你隻需要傳入一個檔案操作符或者一段文本即可得到一個建構完成的文檔對象,有了該對象之後,就可以對該文檔做一些我們想做的操作了。而傳入的文本大都是通過爬蟲爬取過來的,是以 Beautiful Soup 和 requests 庫結合使用體驗更佳。

Beautiful Soup 将複雜的 HTML 文檔轉換成一個複雜的樹形結構,每個節點都是 Python 對象,所有對象可以歸納為 4 種: Tag,NavigableString,BeautifulSoup,Comment。

Tag 就是 HTML 的一個标簽,比如 div,p 标簽等,也是我們用的最多的一個對象。

NavigableString 名額簽内部的文字,直譯就是可周遊的字元串。

BeautifulSoup 指一個文檔的全部内容,可以當成一個 Tag 來處理。

Comment 是一個特殊的 NavigableString,其輸出内容不包括注視内容。

為了故事的順利發展,我們先定義一串 HTML 文本,下文的所有例子都是基于這段文本的。

Tag 有兩個很重要的屬性,name 和 attributes。期中 name 就是标簽的名字,attributes 是标簽屬性。标簽的名字和屬性是可以被修改的,注意,這種修改會直接改變 BeautifulSoup 對象。

由以上例子我麼可以看出,可以直接通過點屬性的方法來擷取 Tag,但是這種方法隻能擷取第一個标簽。同時我們可以多次調用點屬性這個方法,來擷取更深層次的标簽。

如果想獲得所有的某個名字的标簽,則可以使用 find_all(tag_name) 函數。

我們可以使用 .contents 将 tag 以清單方式輸出,即将 tag 的子節點格式化為清單,這很有用,意味着可以通過下标進行通路指定節點。同時我們還可以通過 .children 生成器對節點的子節點進行周遊。

.children 隻可以擷取 tag 的直接節點,而擷取不到子孫節點,.descendants 可以滿足你。

通過 .parent 屬性擷取标簽的父親節點。 title 的父标簽是 head,html 的父标簽是 BeautifulSoup 對象,而 BeautifulSoup 對象的父标簽是 None。

同時,我們可以通過 parents 得到指定标簽的所有父親标簽。

通過 .next_sibling 和 .previous_sibling 來擷取下一個标簽和上一個标簽。

你可能會納悶,調用了兩次 next_sibling 怎麼隻有一個輸出呢,這方法是不是有 bug 啊。事實上是 div 的第一個 next_sibling 是div 和 p 之間的換行符。這個規則對于 previous_sibling 同樣适用。

另外,我們可以通過 .next_siblings 和 .previous_siblings 屬性可以對目前節點的兄弟節點疊代輸出。在該例子中,我們在每次輸出前加了字首,這樣就可以更直覺的看到 dib 的第一個 previous_sibling 是換行符了。

通過 .next_element 和 .previous_element 擷取指定标簽的前一個或者後一個被解析的對象,注意這個和兄弟節點是有所不同的,兄弟節點是指有相同父親節點的子節點,而這個前一個或者後一個是按照文檔的解析順序來計算的。

比如在我們的文本 html_doc 中,head 的兄弟節點是 body(不考慮換行符),因為他們具有共同的父節點 html,但是 head 的下一個節點是 title。即<code>soup.head.next_sibling=title soup.head.next_element=title</code>。

同時這裡還需要注意的是 title 下一個解析的标簽不是 body,而是 title 标簽内的内容,因為 html 的解析順序是打開 title 标簽,然後解析内容,最後關閉 title 标簽。

另外,我們同樣可以通過 .next_elements 和 .previous_elements 來疊代文檔樹。由遺下例子我們可以看出,換行符同樣會占用解析順序,與疊代兄弟節點效果一緻。

本章節介紹了 Beautiful Soup 的使用場景以及操作文檔樹節點的基本操作,看似很多東西其實是有規律可循的,比如函數的命名,兄弟節點或者下一個節點的疊代函數都是擷取單個節點函數的複數形式。

同時由于 HTML 或者 XML 這種循環嵌套的複雜文檔結構,緻使操作起來甚是麻煩,掌握了本文對節點的基本操作,将有助于提高你寫爬蟲程式的效率。

示例代碼:https://github.com/JustDoPython/python-100-day/tree/master/day-065

https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#

關注公衆号:python技術,回複"python"一起學習交流

第65天:爬蟲利器 Beautiful Soup 之周遊文檔

作者:純潔的微笑

出處:www.ityouknow.com

資源:微信搜【純潔的微笑】關注我,回複 【程式員】【面試】【架構師】有我準備的一線程式必備計算機書籍、大廠面試資料和免費電子書。 一共1024G的資料,希望可以幫助大家提升技術和能力。

本文如對您有幫助,還請多幫 【推薦】 下此文。

點我了解:Tooool-程式員一站式導航網站