BeautifulSoup:網頁解析利器上手簡介
關於爬蟲的案例和方法,我們已講過許多。不過在以往的文章中,大多是關注在 如何把網頁上的內容抓取下來 。今天我們來分享下,當你已經把內容爬下來之後, 如何提取出其中你需要的具體資訊 。
網頁被抓取下來,通常就是 str 字串型別的物件 ,要從裡面尋找資訊,最直接的想法就是直接通過字串的 find 方法 和 切片操作 :
s = '<p>價格:15.7 元</p>' start = s.find('價格:') end = s.find(' 元') print(s[start+3:end]) # 15.7
這能應付一些極簡單的情況,但只要稍稍複雜一點,這麼寫就會累死人。更通用的做法是使用 正則表示式 :
import re s = '<p>價格:15.7 元</p>' r = re.search('[\d.]+', s) print(r.group()) # 15.7
正則表示式是處理文字解析的萬金油,什麼情況都可以應對。但可惜掌握它需要一定的學習成本, 原本我們有一個網頁提取的問題,用了正則表示式,現在我們有了兩個問題。
HTML 文件本身是 結構化的文字 ,有一定的規則,通過它的結構可以簡化資訊提取。於是,就有了 lxml、pyquery、BeautifulSoup 等網頁資訊提取庫。一般我們會用這些庫來提取網頁資訊。其中, lxml 有很高的解析效率,支援 xPath 語法 (一種可以在 HTML 中查詢資訊的規則語法); pyquery 得名於 jQuery(知名的前端 js 庫),可以用類似 jQuery 的語法解析網頁 。但我們今天要說的,是剩下的這個:
BeautifulSoup
BeautifulSoup(下文簡稱 bs)翻譯成中文就是“美麗的湯”,這個奇特的名字來源於《 愛麗絲夢遊仙境 》(這也是為何在其官網會配上奇怪的插圖,以及用《愛麗絲》的片段作為測試文字)。
bs 最大的特點我覺得是 簡單易用 ,不像正則和 xPath 需要刻意去記住很多特定語法,儘管那樣會效率更高更直接。 對大多數 python 使用者來說,好用會比高效更重要 。這也是我自己使用並推薦 bs 的主要原因。
接下來介紹點 bs 的基本方法,讓你看完就能用起來。考慮到“只收藏不看黨”的閱讀體驗,先給出一個“ 嫌長不看版 ”的總結:
- 隨 anaconda 附帶,也可以通過 pip 安裝
- 指定 不同解析器在效能、容錯性上會有差異 ,導致結果也可能不一樣
- 基本使用流程: 通過文字初始化 bs 物件 -> 通過 find/find_all 或其他方法檢測資訊 -> 輸出或儲存
- 可以迭代式的查詢,比如先定位出一段內容,再其上繼續檢索
- 開發時應注意不同方法的返回型別,出錯時多看報錯、多加輸出資訊
- 官方文件 很友好,也有中文,推薦閱讀
安裝
推薦使用 pip 進行安裝(關於 pip 見前文《 Crossin:如何安裝 Python 的第三方模組 》):
pip install beautifulsoup4
要注意,包名是 beautifulsoup4 ,如果不加上 4,會是老版本也就是 bs3,它是為了相容性而存在,目前已不推薦。我們這裡說 bs,都是指 bs4。
bs4 也可以直接通過安裝 anaconda 獲得(介紹見前文《 Crossin:Python資料科學環境:Anaconda 瞭解一下 》)。
bs 在使用時需要指定一個“ 解析器 ”:
- html.parse - python 自帶,但容錯性不夠高,對於一些寫得不太規範的網頁會丟失部分內容
- lxml - 解析速度快,需額外安裝
- xml - 同屬 lxml 庫,支援 XML 文件
- html5lib - 最好的容錯性,但速度稍慢
這裡的 lxml 和 html5lib 都需要額外安裝,不過如果你用的是 anaconda,都是一併安裝好的。
快速上手
我們就用官網上的文件作例子:
html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <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> """
使用 bs 的初始化操作,是用文字建立一個 BeautifulSoup 物件,建議手動指定解析器:
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc, 'html.parser')
獲取其中的某個結構化元素及其屬性:
soup.title# title 元素 # <title>The Dormouse's story</title> soup.p# 第一個 p 元素 # <p class="title"><b>The Dormouse's story</b></p> soup.p['class']# p 元素的 class 屬性 # ['title'] soup.p.b# p 元素下的 b 元素 # <b>The Dormouse's story</b> soup.p.parent.name# p 元素的父節點的標籤 # body
並不是所有資訊都可以簡單地通過結構化獲取,通常使用 find 和 find_all 方法進行查詢:
soup.find_all('a')# 所有 a 元素 # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, #<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, #<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] soup.find(id='link3')# id 為 link3 的元素 # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a
- find 和 find_all 可以有多個搜尋條件疊加,比如 find('a', id='link3', class_='sister')
- find 返回的是一個 bs4.element.Tag 物件 ,這個物件可以進一步進行搜尋。如果有多個滿足的結果,find 只返回第一個 ;如果沒有,返回 None。
- find_all 返回的是一個 由 bs4.element.Tag 物件組成的 list ,不管找到幾個或是沒找到,都是 list。
輸出:
x = soup.find(class_='story') x.get_text()# 僅可見文字內容 # 'Once upon a time there were three little sisters; and their names were\nElsie,\nLacie and\nTillie;\nand they lived at the bottom of a well.' x.prettify()# 元素完整內容 # '<p class="story">\n Once upon a time there were three little sisters; and their names were\n <a class="sister" href="http://example.com/elsie" id="link1">\nElsie\n </a>\n ,\n <a class="sister" href="http://example.com/lacie" id="link2">\nLacie\n </a>\n and\n <a class="sister" href="http://example.com/tillie" id="link3">\nTillie\n </a>\n ;\nand they lived at the bottom of a well.\n</p>\n'
如果你有前端開發經驗,對 CSS 選擇器很熟悉,bs 也為你提供了相應的方法:
soup.select('html head title') # [<title>The Dormouse's story</title>] soup.select('p > #link1') # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
以上就是 BeautifulSoup 的一個極簡上手介紹,對於 bs 能做什麼,想必你已有了一個初步認識。如果你要在開發中使用,建議再看下它的 官方文件 。文件寫得很清楚,也有中文版,你只要看了最初的一小部分,就可以在程式碼中派上用場了。更多的細節可以在使用時進一步搜尋具體方法和引數設定。
中文版文件 地址:
Beautiful Soup 4.2.0 文件www.crummy.com
對於爬蟲的其他方面,推薦閱讀我們之前的相關文章:
- Chrome開發者工具:爬蟲必備,掌握它就解決了一半的問題
- requests:讓你的爬蟲開發效率提升8倍
- goose 簡介:一鵝在手,抓遍全球
- IP代理池:聽說你好不容易寫了個爬蟲,結果沒抓幾個就被封了?
- selenium - 祖傳爬蟲利器
- Python爬蟲:一些常用的爬蟲技巧總結
- 爬蟲+網站開發例項:電影票比價網
════