[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

elang發表於2019-02-23

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

網際網路上的資訊量比任何一個人究其一生所能掌握的資訊量都要大的多。所以我們要做的不是在網際網路上逐個訪問資訊,而是需要有一種靈活的方式來收集,整理和分析這些資訊。

我們需要爬取網頁資料。

網頁爬蟲可以自動提取出資料並將資料以一種你可以容易理解的形式呈現出來。在本教程中,我們將重點關注爬蟲技術在金融市場中的應用,但實際上網路內容爬取可用於多個領域。

如果你是一個狂熱的投資者,每天獲知收盤價可能會是一件很痛苦的事,特別是當你需要的資訊分散在多個網頁的時候。我們將通過構建一個網路爬蟲來自動從網上檢索股票指數,從而簡化資料的爬取。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

入門

我們將使用 Python 作為我們的爬蟲語言,還會用到一個簡單但很強大的庫,BeautifulSoup。

  • 對於 Mac 使用者,OS X 已經預裝了 Python。開啟終端並輸入 python --version。你的 Python 的版本應該是 2.7.x。
  • 對於 Windows 使用者,請通過 官方網站 安裝 Python。

接下來,我們需要使用 Python 的包管理工具 pip 來安裝 BeautifulSoup 庫。

在終端中輸入:

easy_install pip  
pip install BeautifulSoup4
複製程式碼

注意:如果你執行上面的命令發生了錯誤,請嘗試在每個命令前面新增 sudo

基礎知識

在我們真正開始編寫程式碼之前,讓我們先了解下 HTML 的基礎知識和一些網頁爬蟲的規則。

HTML 標籤
如果你已經理解了 HTML 的標籤,請跳過這部分。

<!DOCTYPE html>  
<html>  
    <head>
    </head>
    <body>
        <h1> First Scraping </h1>
        <p> Hello World </p>
    <body>
</html>
複製程式碼

下面是一個 HTML 網頁的基本語法。網頁上的每個標籤都定義了一個內容塊:

  1. <!DOCTYPE html>:HTML 文件的開頭必須有的型別宣告。
  2. HTML 的文件包含在標籤 <html> 內。
  3. <head> 標籤裡面是後設資料和 HTML 文件的指令碼宣告。
  4. <body> 標籤裡面是 HTML 文件的可視部分。
  5. 標題通過 <h1><h6> 的標籤定義。
  6. 段落內容被定義在 <p> 標籤裡。

其他常用的標籤還有,用於超連結的 <a> 標籤,用於顯示錶格的 <table> 標籤,以及用於顯示錶格行的 <tr> 標籤,用於顯示錶格列的 <td> 標籤。

另外,HTML 標籤時常會有 id 或者 class 屬性。id 屬性定義了標籤的唯一標識,並且這個值在當前文件中必須是唯一的。class 屬性用來給具有相同類屬性的 HTML 標籤定義相同的樣式。我們可以使用這些 id 和 class 來幫助我們定位我們要爬取的資料。

需要更多關於 HTML 標籤idclass 的相關內容,請參考 W3Schools 網站的 教程

爬取規則

  1. 你應該在爬取之前先檢查一下網站使用條款。仔細的閱讀其中關於合法使用資料的宣告。一般來說,你爬取的資料不能用於商業用途。
  2. 你的爬取程式不要太有攻擊性地從網站請求資料(就像眾所周知的垃圾郵件攻擊一樣),那可能會對網站造成破壞。確保你的爬蟲程式以合理的方式執行(如同一個人在操作網站那樣)。一個網頁每秒請求一次是個很好的做法。
  3. 網站的佈局時不時的會有變化,所以要確保經常訪問網站並且必要時及時重寫你的程式碼。

檢查網頁

讓我們以 Bloomberg Quote 網站的一個頁面為例。

因為有些人會關注股市,那麼我們就從這個頁面上獲取指數名稱(標準普爾 500 指數)和它的價格。首先,從滑鼠右鍵選單中點選 Inspect 選項來檢視頁面。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

試著把滑鼠指標懸浮在價格上,你應該可以看到出現了一個藍色方形區域包裹住了價格。如果你點選,在瀏覽器的控制檯上,這段 HTML 內容就被選定了。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

通過結果,你可以看到價格被好幾層 HTML 標籤包裹著,<div class="basic-quote"><div class="price-container up"><div class="price">

類似的,如果你懸浮並且點選“標準普爾 500 指數”,它被包裹在 <div class="basic-quote"><h1 class="name"> 裡面。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

現在我們通過 class 標籤的幫助,知道了所需資料的確切位置。

編寫程式碼

既然我們知道資料在哪兒了,我們就可以編寫網頁爬蟲了。現在開啟你的文字編輯器。

首先,需要匯入所有我們需要用到的庫。

# import libraries
import urllib2
from bs4 import BeautifulSoup
複製程式碼

接下來,宣告一個網址連結變數。

# specify the url
quote_page = ‘http://www.bloomberg.com/quote/SPX:IND'
複製程式碼

然後,使用 Python 的 urllib2 來請求宣告的 url 指向的 HTML 網頁。

# query the website and return the html to the variable ‘page’
page = urllib2.urlopen(quote_page)
複製程式碼

最後,把頁面內容解析成 BeatifulSoup 的格式,以便我們能夠使用 BeautifulSoup 去處理。。

# parse the html using beautiful soup and store in variable `soup`
soup = BeautifulSoup(page, ‘html.parser’)
複製程式碼

現在我們有一個變數 soup,它包含了頁面的 HTML 內容。這裡我們就可以編寫爬取資料的程式碼了。

還記得資料的獨特的層級結構嗎?BeautifulSoup 的 find() 方法可以幫助我們找到這些層級結構,然後提取內容。在這個例子中,因為這段 HTML 的 class 名稱是唯一的,所有我們很容易找到 <div class="name">

# Take out the <div> of name and get its value
name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
複製程式碼

我們可以通過獲取標籤的 text 屬性來獲取資料。

name = name_box.text.strip() # strip() is used to remove starting and trailing
print name
複製程式碼

類似地,我們也可以獲取價格。

# get the index price
price_box = soup.find(‘div’, attrs={‘class’:’price’})
price = price_box.text
print price
複製程式碼

當你執行這個程式,你可以看到標準普爾 500 指數的當前價格被列印了出來。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

輸出到 Excel CSV

既然我們有了資料,是時候去儲存它了。Excel 的 csv 格式是一個很好的選擇。它可以通過 Excel 開啟,所以你可以很輕鬆的開啟並處理資料。

但是,首先,我們必須把 Python csv 模組匯入進來,還要匯入 datetime 模組來獲取記錄的日期。在 import 部分,加入下面這幾行程式碼。

import csv
from datetime import datetime
複製程式碼

在你的程式碼底部,新增儲存資料到 csv 檔案的程式碼。

# open a csv file with append, so old data will not be erased
with open(‘index.csv’, ‘a’) as csv_file:
 writer = csv.writer(csv_file)
 writer.writerow([name, price, datetime.now()])
複製程式碼

如果你現在執行你的程式,你應該可以匯出一個index.csv檔案,然後你可以用 Excel 開啟它,在裡面可以看到一行資料。

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

如果你每天執行這個程式,你就可以很簡單地獲取標準普爾 500 指數,而不用重複地通過網頁查詢。

進階使用 (高階應用)

多個指數
對你來說,只獲取一個指數遠遠不夠,對不對?我們可以同時提取多個指數。

首先,將 quote_page 變數修改為一個 URL 的陣列。

quote_page = [‘http://www.bloomberg.com/quote/SPX:IND', ‘http://www.bloomberg.com/quote/CCMP:IND']
複製程式碼

然後我們把資料提取程式碼變成 for 迴圈,這樣可以一個接一個地處理 URL,然後把所有的資料都存到元組 data 中。

# for loop
data = []
for pg in quote_page:
 # query the website and return the html to the variable ‘page’
 page = urllib2.urlopen(pg)

# parse the html using beautiful soap and store in variable `soup`
 soup = BeautifulSoup(page, ‘html.parser’)

# Take out the <div> of name and get its value
 name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
 name = name_box.text.strip() # strip() is used to remove starting and trailing

# get the index price
 price_box = soup.find(‘div’, attrs={‘class’:’price’})
 price = price_box.text

# save the data in tuple
 data.append((name, price))
複製程式碼

然後,修改“儲存部分”的程式碼以逐行儲存資料。

# open a csv file with append, so old data will not be erased
with open(‘index.csv’, ‘a’) as csv_file:
 writer = csv.writer(csv_file)
 # The for loop
 for name, price in data:
 writer.writerow([name, price, datetime.now()])
複製程式碼

重新執行程式碼,你應該可以同時提取到兩個指數了。

高階的爬蟲技術

BeautifulSoup 是一個簡單且強大的小規模的網頁爬蟲工具。但是如果你對更大規模的網路資料爬蟲感興趣,那麼你應該考慮使用其他的替代工具。

  1. Scrapy,一個強大的 Python 爬蟲框架
  2. 嘗試將你的程式碼與一些公共 API 整合。資料檢索的效率要遠遠高於網頁爬蟲的效率。比如,看一下 Facebook Graph API,它可以幫助你獲取未在 Facebook 網頁上顯示的隱藏資料。
  3. 如果爬取資料過大,請考慮使用一個後臺資料庫來儲存你的資料,比如 MySQL

採用 DRY 方法

[譯] 如何使用 Python 和 BeautifulSoup 爬取網站內容

DRY(Don't Repeat Yourself)代表“不要重複自己的工作”,嘗試把你每日工作都自動化,像 這個人 做的那樣。可以考慮一些有趣的專案,可能是跟蹤你的 Facebook 好友的活躍時間(需要獲得他們的同意),或者是獲取論壇的演講列表並嘗試進行自然語言處理(這是當前人工智慧的一個熱門話題)!

如果你有任何問題,可以隨時在下面留言。

參考:

這篇文章最初發表在 Altitude Labs部落格上,作者是我們的軟體工程師 Leonard MokAltitude Labs 是一家專門從事 React 移動應用定製開發的軟體代理商。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章