這裡介紹如何使用 Python 的 Beautiful Soup 模組自動下載並解析網頁資料,開發典型的網路爬蟲程式。
Beautiful Soup 是一個 Python 的函式庫模組,可以讓開發者僅須撰寫非常少量的程式碼,就可以快速解析網頁 HTML 碼,從中翠取出使用者有興趣的資料、去蕪存菁,降低網路爬蟲程式的開發門檻、加快程式撰寫速度。
Beautiful Soup 這套模組的網頁結構搜尋與萃取功能相當完整,這裡我們只介紹比較常用的幾種功能,更詳細的用法請參考 Beautiful Soup 官方的說明文件。
安裝 Beautiful Soup
Beautiful Soup 可以使用 pip
安裝:
# 安裝 Python 2 的 Beautiful Soup 4 模組 pip install beautifulsoup4 # 安裝 Python 3 的 Beautiful Soup 4 模組 pip3 install beautifulsoup4
在 Ubuntu Linux 中亦可使用 apt 安裝:
# 安裝 Python 2 的 Beautiful Soup 4 模組 sudo apt-get install python-bs4 # 安裝 Python 3 的 Beautiful Soup 4 模組 sudo apt-get install python3-bs4
Beautiful Soup 基本用法
Beautiful Soup 的運作方式就是讀取 HTML 原始碼,自動進行解析並產生一個 BeautifulSoup
物件,此物件中包含了整個 HTML 文件的結構樹,有了這個結構樹之後,就可以輕鬆找出任何有興趣的資料了。
以下是一個簡單的小程式,示範如何使用 Beautiful Soup 模組解析原始的 HTML 程式碼:
# 引入 Beautiful Soup 模組 from bs4 import BeautifulSoup # 原始 HTML 程式碼 html_doc = """ <html><head><title>Hello World</title></head> <body><h2>Test Header</h2> <p>This is a test.</p> <a id="link1" href="/my_link1">Link 1</a> <a id="link2" href="/my_link2">Link 2</a> <p>Hello, <b class="boldtext">Bold Text</b></p> </body></html> """ # 以 Beautiful Soup 解析 HTML 程式碼 soup = BeautifulSoup(html_doc, 'html.parser')
這裡的 soup
就是解析完成後,所產生的結構樹物件,接下來所有資料的搜尋、萃取等操作都會透過這個物件來進行。
首先我們可以將完整個 HTML 結構經過排版後輸出,觀察整份文件的輪廓:
# 輸出排版後的 HTML 程式碼 print(soup.prettify())
<html> <head> <title> Hello World </title> </head> <body> <h2> Test Header </h2> <p> This is a test. </p> <a href="/my_link1" id="link1"> Link 1 </a> <a href="/my_link2" id="link2"> Link 2 </a> <p> Hello, <b class="boldtext"> Bold Text </b> </p> </body> </html>
取得節點文字內容
若要輸出網頁標題的 HTML 標籤,可以直接指定網頁標題標籤的名稱(title
),即可將該標籤的節點抓出來:
# 網頁標題 HTML 標籤 title_tag = soup.title print(title_tag)
<title>Hello World</title>
HTML 標籤節點的文字內容,可以透過 string
屬性存取:
# 網頁的標題文字 print(title_tag.string)
Hello World
搜尋節點
我們可以使用 find_all
找出所有特定的 HTML 標籤節點,再以 Python 的迴圈來依序輸出每個超連結的文字:
# 所有的超連結 a_tags = soup.find_all('a') for tag in a_tags: # 輸出超連結的文字 print(tag.string)
Link 1 Link 2
取出節點屬性
若要取出 HTML 節點的各種屬性,可以使用 get
,例如輸出每個超連結的網址(href
屬性):
for tag in a_tags: # 輸出超連結網址 print(tag.get('href'))
/my_link1 /my_link2
同時搜尋多種標籤
若要同時搜尋多種 HTML 標籤,可以使用 list 來指定所有的要列出的 HTML 標籤名稱:
# 搜尋所有超連結與粗體字 tags = soup.find_all(["a", "b"]) print(tags)
[<a href="/my_link1" id="link1">Link 1</a>, <a href="/my_link2" id="link2">Link 2</a>, <b class="boldtext">Bold Text</b>]
限制搜尋節點數量
find_all
預設會輸出所有符合條件的節點,但若是遇到節點數量很多的時候,就會需要比較久的計算時間,如果我們不需要所有符合條件的節點,可以用 limit
參數指定搜尋節點數量的上限值,這樣它就只會找出前幾個符合條件的節點:
# 限制搜尋結果數量 tags = soup.find_all(["a", "b"], limit=2) print(tags)
[<a href="/my_link1" id="link1">Link 1</a>, <a href="/my_link2" id="link2">Link 2</a>]
如果只需要抓出第一個符合條件的節點,可以直接使用 find
:
# 只抓出第一個符合條件的節點 a_tag = soup.find("a") print(a_tag)
<a href="/my_link1" id="link1">Link 1</a>
遞迴搜尋
預設的狀況下,find_all
會以遞迴的方式尋找所有的子節點:
# 預設會以遞迴搜尋 soup.html.find_all("title")
[<title>Hello World</title>]
如果想要限制 find_all
只找尋次一層的子節點,可以加上 recursive=False
關閉遞迴搜尋功能:
# 不使用遞迴搜尋,僅尋找次一層的子節點 soup.html.find_all("title", recursive=False)
[]
接下來我們要介紹一些更詳細的使用方式,請繼續閱讀下一頁。
Aileen
Thank you for the post. it helps me a lot!
many thanks!!
Martina
很多地方都只是写prettify()可以把代码格式化。。。解释得一点都不通俗,还是不明白。你解释得清楚多了,一目了然!谢谢!
ZHONG
先感謝作者對這部分的用心
內容相當充實,對新手來說也很好上手
在試過google搜尋範例之後我有個問題
如果我想要一次搜尋多一些資料該怎麼做
目前所知是第1頁的’start’會是’0’,第2頁是’10’,以此類推
Wilson
感謝作者那麼用心的整理出這些步驟。
想知道到如何設定Google 的設計抓取資料的量
W.
謝謝站長寫得真好 容易看懂重要的功能 還有很實用的範例
XXL
寫得太棒了!!!
H
範例列出得十分清晰易懂,十分感謝!
FF
怎麼去提取數據從一個jQuery.get() 的網頁應用.
查看網頁源代碼 找不到該網頁所展示的數據資料
Jay
寫的真的很好,棒!
neoyang
高手