【我們為什麼挑選這篇文章】爬蟲應用大概是 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 服務預告大眾失業潮
如何成為好的資料學家?亞馬遜資料科學家的四個建議:把課本丟了,去實做
你對製作這些科技趨勢內容有興趣嗎? 想從 TO 讀者變成 TO 製作者嗎? 對內容策展有無比興趣的你,快加入我們的編輯團隊吧! TechOrange 社群編輯擴大徵才中 >> 詳細內容 意者請提供履歷自傳以及文字作品,寄至 jobs@fusionmedium.com 來信主旨請註明:【應徵】TechOrange 職缺名稱:您的大名