使用 Python 的 requests 和 Beautiful Soup 來分析網頁
瀏覽網頁可能佔了你一天中的大部分時間。然而,你總是需要手動瀏覽,這很討厭,不是嗎?你必須打開瀏覽器,然後訪問一個網站,單擊按鈕,移動滑鼠……相當費時費力。如果能夠通過代碼與互聯網交互,豈不是更好嗎?
在 Python 的 requests
模塊的幫助下,你可以使用 Python 從互聯網中獲取數據:
import requests
DATA = "https://opensource.com/article/22/5/document-source-code-doxygen-linux"
PAGE = requests.get(DATA)
print(PAGE.text)
在以上代碼示例中,你首先導入了 requests
模塊。接著,你創建了兩個變數:其中一個叫做 DATA
,它用來保存你要下載的 URL。在之後的代碼中,你將能夠在每次運行應用程序時提供不同的 URL。不過,就目前而言,最簡單的方法是「硬編碼」一個測試 URL,以達到演示目的。
另一個變數是 PAGE
。代碼讀取了存儲在 DATA
中的 URL,然後把它作為參數傳入 requests.get
函數,最後用變數 PAGE
來接收函數的返回值。requests
模塊及其 .get
函數的功能是:「讀取」一個互聯網地址(一個 URL)、訪問互聯網,並下載位於該地址的任何內容。
當然,其中涉及到很多步驟。幸運的是,你不必自己弄清楚,這也正是 Python 模塊存在的原因。最後,你告訴 Python 列印 requests.get
存儲在 PAGE
變數的 .text
欄位中的所有內容。
Beautiful Soup
如果你運行上面的示例代碼,你會得到示例 URL 的所有內容,並且,它們會不加選擇地輸出到你的終端里。這是因為在代碼中,你對 requests
收集到的數據所做的唯一事情,就是列印它。然而,解析文本才是更加有趣的。
Python 可以通過其最基本的功能來「讀取」文本,但解析文本允許你搜索模式、特定單詞、HTML 標籤等。你可以自己解析 requests
返回的文本,不過,使用專門的模塊會容易得多。針對 HTML 和 XML 文本,我們有 Beautiful Soup 庫。
下面這段代碼完成了同樣的事情,只不過,它使用了 Beautiful Soup 來解析下載的文本。因為 Beautiful Soup 可以識別 HTML 元素,所以你可以使用它的一些內置功能,讓輸出對人眼更友好。
例如,在程序的末尾,你可以使用 Beautiful Soup 的 .prettify
函數來處理文本(使其更美觀),而不是直接列印原始文本:
from bs4 import BeautifulSoup
import requests
PAGE = requests.get("https://opensource.com/article/22/5/document-source-code-doxygen-linux")
SOUP = BeautifulSoup(PAGE.text, 'html.parser')
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
# do a thing here
print(SOUP.prettify())
通過以上代碼,我們確保了每個打開的 HTML 標籤都輸出在單獨的一行,並帶有適當的縮進,以幫助說明標籤的繼承關係。實際上,Beautiful Soup 能夠通過更多方式來理解 HTML 標籤,而不僅僅是將它列印出來。
你可以選擇列印某個特定標籤,而不是列印整個頁面。例如,嘗試將列印的選擇器從 print(SOUP.prettify())
更改為:
print(SOUP.p)
這隻會列印一個 <p>
標籤。具體來說,它只列印遇到的第一個 <p>
標籤。要列印所有的 <p>
標籤,你需要使用一個循環。
循環
使用 Beautiful Soup 的 find_all
函數,你可以創建一個 for
循環,從而遍歷 SOUP
變數中包含的整個網頁。除了 <p>
標籤之外,你可能也會對其他標籤感興趣,因此最好將其構建為自定義函數,由 Python 中的 def
關鍵字(意思是 「定義」 )指定。
def loopit():
for TAG in SOUP.find_all('p'):
print(TAG)
你可以隨意更改臨時變數 TAG
的名字,例如 ITEM
或 i
或任何你喜歡的。每次循環運行時,TAG
中都會包含 find_all
函數的搜索結果。在此代碼中,它搜索的是 <p>
標籤。
函數不會自動執行,除非你顯式地調用它。你可以在代碼的末尾調用這個函數:
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
# do a thing here
loopit()
運行代碼以查看所有的 <p>
標籤和它們的內容。
只獲取內容
你可以通過指定只需要 「 字元串 」(它是 「 單詞 」 的編程術語)來排除列印標籤。
def loopit():
for TAG in SOUP.find_all('p'):
print(TAG.string)
當然,一旦你有了網頁的文本,你就可以用標準的 Python 字元串庫進一步解析它。例如,你可以使用 len
和 split
函數獲得單詞個數:
def loopit():
for TAG in SOUP.find_all('p'):
if TAG.string is not None:
print(len(TAG.string.split()))
這將列印每個段落元素中的字元串個數,省略那些沒有任何字元串的段落。要獲得字元串總數,你需要用到變數和一些基本數學知識:
def loopit():
NUM = 0
for TAG in SOUP.find_all('p'):
if TAG.string is not None:
NUM = NUM + len(TAG.string.split())
print("Grand total is ", NUM)
Python 作業
你可以使用 Beautiful Soup 和 Python 提取更多信息。以下是有關如何改進你的應用程序的一些想法:
- 接受輸入,這樣你就可以在啟動應用程序時,指定要下載和分析的 URL。
- 統計頁面上圖片(
<img>
標籤)的數量。 - 統計另一個標籤中的圖片(
<img>
標籤)的數量(例如,僅出現在<main>
div 中的圖片,或僅出現在</p>
標籤之後的圖片)。
via: https://opensource.com/article/22/6/analyze-web-pages-python-requests-beautiful-soup
作者:Seth Kenlon 選題:lkxed 譯者:lkxed 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive