
【我們為什麼挑選這篇文章】爬蟲應用大概是 Python 最擅長,也是最初階的練習功能之一了。透過本文深入淺出的,帶有解說的程式碼,能夠讓你用最簡單的方式理解爬蟲原理。而理解之後,才能試著串接各種 API 達到自動化手邊工作的最大原則。
如果你不知道爬蟲可以幹嘛,除了像本文拿來爬梳股票網站之外,也可以閱讀《TO》的文章:電商爬蟲大戰:亞馬遜網站有 80% 以上的點擊率,來自對手的爬蟲機器人。(責任編輯:陳君毅)
網絡上的信息是任何人窮極一生也無法全部了解的。你需要的或許不是簡單的獲得信息,而是一個可以收集,整理,分析信息,並且具有拓展性的方法。
你需要網頁抓取(Web scraping)技術。
網頁抓取可以自動提取網站上的數據信息,並把這些信息用一種容易理解的格式呈現出來。網頁抓取應用廣泛, 在本教程中我們將重點講解它在金融市場領域的運用。
如果你是個投資達人,每天查找收盤價一定是個煩心事,更不用提數據來源於多個網站的時候。我們可以用代碼寫一個網絡爬蟲(web scraper) 來幫助我們自動從網站獲取股指信息,從而大大簡化數據提取過程。

我們開始吧。
我們採用 Python 進行網頁數據抓取,並採用簡單強大的 BeautifulSoup 庫完成分析。
- 對於 Mac 用戶來說, OS X 操作系統已經預先安裝好 Python。您需要打開終端並輸入 python –version。您應該可以看到 python 的版本為 2.7.x。
- 對於 Windows 用戶而言,請由官方網站安裝 Python。
下一步,我們需要利用 pip 命令獲取 BeautifulSoup 庫。Pip 是 Python 中管理庫和包的工具。
在終端中輸入:
easy_install pip
pip install BeautifulSoup4
注意:如果您不能運行上面的命令,在每行前面加上 sudo 再試試。
HTML 標籤基礎知識
如果你已經充分理解 HTML 標籤,請跳過這一部分。這是 HTML 網頁的基本語法。
每一對 <tag> 標籤內包含網頁的一段代碼:
1. <!DOCTYPE html>: HTML 文件必須以文件類型聲明開頭
2. HTML 文件包含在<html>和<html/>標籤之間
3. 元(meta)和腳本(script)聲明包含在<head>和</head>標籤之間
4. 網站上可見的部分包含在<body>和</body>標籤之間
5. <h1>和<h6>標籤之間的部分為網站標題
6. <p>標籤用於定義段落
其他有用的標籤還有:<a>是超鏈接的標籤,<table>是表格的標籤,<tr>是表格行的標籤,<td>是表格列的標籤。
並且,HTML 標籤常常帶有標識碼(id) 或類(class)屬性,標識碼用來唯一的識別某個 HTML 標籤,並且標識碼的值在整個 HTML 文件中是唯一的。類屬性可以定義同類 HTML 標籤相同的樣式。我們可以利用標識碼和類來幫助我們定位想要的數據。
如果您想了解關於 HTML 標籤,標識碼和類的更多內容,請參考 W3Schools 出品的教程。
網絡抓取規則
1.在您進行網絡抓取時,你應該查看網站的條款和條件。請仔細閱讀數據合法使用聲明。通常情況下,您抓取的數據不能商用。
2.您的程序不要過於頻繁的向網站發出數據請求(也被稱為垃圾請求),這種做法可能會使網站崩潰。請確保您的程序行為合理(也就是說和人類的行為相似)。對一個網站每秒進行一次數據請求是比較好的做法。
3. 網站的佈局隨時間不斷變化,所以請您確保時常重新訪問網站,如果需要的話,修改抓取代碼。
查看頁面
讓我們以 Bloomberg Quote 網站的其中一頁為例。
作為一個關注股票市場的投資人,我們想要從這一頁得到股指名稱(標準普爾 500 指數)和價格。首先,右鍵點擊打開瀏覽器的檢查器(inspector),查看網頁。

請嘗試把光標放在股指價格上,你應該可以看到價格周圍的藍色方塊,如果你點擊這個方塊,就可以選中瀏覽器控制台相應的 HTML 代碼。

從結果可以看出,價格信息包含在好幾層 HTML 標籤中:
<div class=”basic-quote”> →
<div class=”price-container up”> →
<div class=”price”>
同樣的,如果你把光標放在名稱「標準普爾指數」上,並點擊,可以看到控制台裡這個信息包含在標籤< iv class=”basic-quote”>及< h1 class=”name”>之內。
現在我們知道如何依靠類標籤找到我們需要的數據了。
學習代碼
現在我們知道所需數據的位置,我們可以開始寫代碼構建我們的網絡爬蟲了。現在請打開您的文字編輯工具!
首先我們要導入我們要用的各種庫。
# 導入各種庫
import urllib2
from bs4 import BeautifulSoup
然後,我們定義一個變量(quote_page)並賦值為網站的網址鏈接。
# 賦值網站鏈接
quote_page = ‘http://www.bloomberg.com/quote/SPX:IND’
接著,利用 Python 的 urllib2 庫獲取方才定義的網址 quote_page 的 HTML 網頁信息。
# 檢索網站並獲取 html 代碼,存入變量”page”中
page = urllib2.urlopen(quote_page)
最後,我們把網頁解析為 BeautifulSoup 格式,以便我們用 BeautifulSoup 庫來分析網頁。
# 用beautifulSoup 解析HTML代碼並存入變量“soup”中`
soup = BeautifulSoup(page, ‘html.parser’)
現在我們有了包含整個網頁的 HTML 代碼的變量 soup。我們就從 soup 開始著手提取信息。
別忘了我們的數據存儲在特有的層次中。BeautifulSoup 庫中的 find()函數可以幫助我們進入不同的層次提取內容。我們需要的 HTML 類「名稱」在整個網頁中是獨一無二的,因此我們可以簡單的查找<div class=”name”>
# 獲取“名稱”類的<div>代碼段落並提取相應值
name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
在我們得到標籤之後,我們可以用 name_box 的 text 屬性獲取相應值
name = name_box.text.strip()
print name
# strip() 函數用於去除前後空格
採用相似的方法,我們可以得到股指價格數據。
# 獲取股指價格數據
price_box = soup.find(‘div’, attrs={‘class’:’price’})
price = price_box.text
print price

當你運行程序時,應該可以看到程序輸出當前的標普 500 指數的價格。
導出 Excel CSV 格式數據
我們已經學會如何獲取數據,現在來學習如何存儲數據了。Excel 逗號隔開的數據格式(CSV)不失為一個好選擇。這樣我們就可以在 Excel 中打開數據文件進行查看和進一步處理。
在此之前,我們需要導入 Python 的 csv 模塊和 datetime 模塊。Datetime 模塊用於獲取數據記錄時間。請將下面幾行代碼插入您的導入代碼部分。
import csv
from datetime import datetime
在您代碼的最下方,加上把數據寫入 CSV 文件的代碼。
# 以「添加」模式打開一個 csv 文件,以保證文件原有信息不被覆蓋
with open(‘index.csv’, ‘a’) as csv_file:
writer = csv.writer(csv_file)
writer.writerow([name, price, datetime.now()])

現在如果運行程序,您應該可以導出一個 index.csv 文件。您可以在 Excel 中打開文件,看到裡面有如圖所示的一行數據。
所以如果您每天都運行這個程序,您就可以很簡單的獲取標準普爾指數價格,不需要像之前一樣在網站上翻找。
更進一步(高級用法)
抓取一個股指信息對您來說不夠,對嗎?我們可以試試同時提取多個股指信息。首先,我們需要修改 quote_page,把它定義為網址的數組。
quote_page = [‘http://www.bloomberg.com/quote/SPX:IND’, ‘http://www.bloomberg.com/quote/CCMP:IND’]
然後我們把數據提取部分代碼改成一個 for 循環。這個循環可以一一處理網址,並以元組(tuple)類型把所有數據存入變量 data.
# for 循環
data = []
for pg in quote_page:
# 檢索網站並返回HTML代碼,存入變量’page’
page = urllib2.urlopen(pg)
# 用 beautifulSoup 解析 HTML 代碼並存入變量`soup`
soup = BeautifulSoup(page, ‘html.parser’)
# 獲取“名稱”類的<div>代碼段落並提取相應值
name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
name = name_box.text.strip() # strip() is used to remove starting and trailing
# 獲取股指價格數據
price_box = soup.find(‘div’, attrs={‘class’:’price’})
price = price_box.text
# 用元組類型存儲數據
data.append((name, price))
並且,修改保存部分以便一行行保存數據
# 以“添加”模式打開一個 csv 文件,以保證文件原有信息不被覆蓋
with open(‘index.csv’, ‘a’) as csv_file:
writer = csv.writer(csv_file)
# for 循環
for name, price in data:
writer.writerow([name, price, datetime.now()])
重新運行程序,您應該可以同時提取兩個股指價格信息了!
高級抓取技術
BeautifulSoup 庫使用簡單,能很好的完成小量的網站抓取。但是如果您對大量的抓取信息感興趣,您可以考慮其他方法:
1. 強大的 Python 數據抓取框架 Scrapy。
2. 您可以試試把一些公共應用程序接口(Application programming interface, API)整合入您的代碼。這個獲取數據的方法遠比網頁抓取高效。舉個例子來說,您可以試試 Facebook Graph API,這個應用程序接口可以幫助您獲取臉書網站上不顯示的隱藏信息。
3. 如果數據量過大,您可以考慮使用類似 MySQL 的數據庫後端來存儲數據。
採取「別重複」方法:DRY
DRY 是「別重複你做過的事」的英文簡寫。
您可以嘗試像鏈接中的這個人一樣把日常的工作自動化。同時您還可以考慮其他有趣的項目,比如說掌握您的臉書好友的上線時間(當然在徵得他們同意的情況下),或者獲取某個論壇的講座主題列表來嘗試自然語言處理(這是目前人工智能的熱門話題)!

——
(本文經 大數據文摘微信公眾平台(ID:BigDataDigest) 授權轉載,並同意 TechOrange 編寫導讀與修訂標題,原文標題為〈手把手| 範例+代碼:一文帶你上手Python網頁抓取神器BeautifulSoup庫〉,原文鏈接 ,首圖來源:Marcus Brown, CC Licensed。)
延伸閱讀
2017 年 15 個最好用 Python 庫,學習資料科學、機器學習絕對不容錯過
要追,就追最好的!全球 AI 社群最具影響力的意見領袖、品牌、知識社群總整理
只花六秒滅掉整個產業,中國螞蟻金服 AI 服務預告大眾失業潮
如何成為好的資料學家?亞馬遜資料科學家的四個建議:把課本丟了,去實做



