用Python進行網頁抓取
引言
從網頁中提取信息的需求日益劇增,其重要性也越來越明顯。每隔幾周,我自己就想要到網頁上提取一些信息。比如上周我們考慮建立一個有關各種數據科學在線課程的歡迎程度和意見的索引。我們不僅需要找出新的課程,還要抓取對課程的評論,對它們進行總結後建立一些衡量指標。這是一個問題或產品,其功效更多地取決於網頁抓取和信息提取(數據集)的技術,而非以往我們使用的數據匯總技術。
網頁信息提取的方式
從網頁中提取信息有一些方法。使用API可能被認為是從網站提取信息的最佳方法。幾乎所有的大型網站,像Twitter、Facebook、Google、Twitter、StackOverflow都提供API以更為結構化的方式訪問該網站的數據。如果可以直接通過API得到所需要的信息,那麽這個方法幾乎總是優於網頁抓取方法。因為如果可以從數據提供方得到結構化的數據,為什麽還要自己建立一個引擎來提取同樣的數據?
不幸的是,並不是所有的網站都提供API。一些網站是不願意讓讀者通過結構化的方式抓取大量的信息,另一些網站是因為缺乏相關的技術知識而不能提供API。在這樣的情況下,該怎麽做?好吧,我們需要通過網頁抓取來獲得數據。
當然還有一些像RSS訂閱等的其它方式,但是由於使用上的限制,因此我將不在這裏討論它們。
什麽是網頁抓取?
網頁抓取是一種從網站中獲取信息的計算機軟件技術。這種技術主要聚焦於把網絡中的非結構化數據(HTML 格式)轉變成結構化數據(數據庫或電子表格)。
可以用不同的方式實施網頁抓取,包括從Google Docs到幾乎所有的編程語言。由於Python的易用性和豐富的生態系統,我會選擇使用Python。
Python中的BeautifulSoup庫可以協助完成這一任務。在本文中,我將會利用Python編程語言給你看學習網頁抓取最簡單的方式。
對於需要借助非編程方式提取網頁數據的讀者,可以去import.io上看看。那上面有基於圖形用戶界面的驅動來運行網頁抓取的基礎操作,計算機迷們可以繼續看本文!
網頁抓取所需要的庫
我們都知道Python是一門開源編程語言。你也許能找到很多庫來實施一個功能。因此,找出最好的庫是非常必要的。我傾向於使用BeautifulSoup (Python庫),因為它的使用簡單直觀。準確地說,我會用到兩個Python模塊來抓取數據:
?Urllib2:它是一個Python模塊,用來獲取URL。
?BeautifulSoup:它是一個神奇的工具,用來從網頁中提取信息。可以用它從網頁中提取表格、列表、段落,也可以加上過濾器。
在本文中,我們將會用最新版本,BeautifulSoup 4。可以在它的文檔頁面查看安裝指南。
BeautifulSoup不幫我們獲取網頁,這是我將urllib2和BeautifulSoup 庫一起使用的原因。除了BeautifulSoup之外,Python還有其它一些方法用於HTML的抓取。如:
?mechanize
?scrapemark
?scrapy
基礎-熟悉HTML(標簽)
在進行網頁抓取時,我們需要處理html標簽。因此,我們必須先好好理解一下標簽。如果已經了解HTML的基礎知識,可以跳過這一節。以下是HTML的基本語法:
該語法的各種標簽的解釋如下:
1.<!DOCTYPE html>:html文檔必須以類型聲明開始
2.html文檔寫在<html> 和</html>標簽之間
3.html文檔的可見部分寫在<body> 和</body>標簽之間
4.html頭使用<h1> 到<h6> 標簽定義
5.html段落使用<p>標簽定義
其它有用的HTML標簽是:
1.html鏈接使用<a>標簽定義,“<a href=“http://www.test.com”>這是一個測試鏈接.com</a>”
2.html表格使用<Table>定義,行用<tr>表示,行用<td>分為數據
3.html列表以<ul>(無序)和<ol>(有序)開始,列表中的每個元素以<li>開始
如果不熟悉這些HTML標簽,我建議到W3schools上學習HTML教程。這樣對HTML標簽會有個清楚的理解。
使用BeautifulSoup抓取網頁
在這裏,我將從維基百科頁面上抓取數據。我們的最終目的是抓取印度的邦、聯邦首府的列表,以及一些基本細節,如成立信息、前首府和其它組成這個維基百科頁面的信息。讓我們一步一步做這個項目來學習:
1.導入必要的庫
2.使用“prettify”函數來看HTML頁面的嵌套結構
如上所示,可以看到HTML標簽的結構。這將有助於了解不同的可用標簽,從而明白如何使用它們來抓取信息。
3.處理HTML標簽
a.soup.<tag>:返回在開始和結束標簽之間的內容,包括標簽在內。
b.soup.<tag>.string: 返回給定標簽內的字符串
c.找出在標簽<a>內的鏈接:我們知道,我們可以用標簽<a>標記一個鏈接。因此,我們應該利用soup.a 選項,它應該返回在網頁內可用的鏈接。我們來做一下。
如上所示,可以看到只有一個結果。現在,我們將使用“find_all()”來抓取<a>中的所有鏈接。
上面顯示了所有的鏈接,包括標題、鏈接和其它信息。現在,為了只顯示鏈接,我們需要使用get的“href”屬性:遍歷每一個標簽,然後再返回鏈接。
4.找到正確的表:當我們在找一個表以抓取邦首府的信息時,我們應該首先找出正確的表。讓我們寫指令來抓取所有表標簽中的信息。
現在為了找出正確的表,我們將使用表的屬性“class(類)”,並用它來篩選出正確的表。在chrome瀏覽器中,可以通過在所需的網頁表格上單擊右鍵來查詢其類名–>檢查元素–>復制該類名或通過上述命令的輸出找到正確的表的類名。
5.提取信息放入DataFrame:在這裏,我們要遍歷每一行(tr),然後將tr的每個元素(td)賦給一個變量,將它添加到列表中。讓我們先看看表格的HTML結構(我不想抓取表格標題的信息<th>)
如上所示,你會註意到<tr>的第二個元素在< th >標簽內,而不在<td>標簽內。因此,對這一點我們需要小心。現在要訪問每個元素的值,我們會使用每個元素的“find(text=True)”選項。讓我們看一下代碼:
最後,我們在dataframe內的數據如下:
類似地,可以用BeautifulSoup實施各種其它類型的網頁抓取。這將減輕從網頁上手工收集數據的工作。也可以看下其它屬性,如.parent,.contents,.descendants 和.next_sibling,.prev_sibling以及各種用於標簽名稱瀏覽的屬性。這些將有助於您有效地抓取網頁。
但是,為什麽我不能只使用正則表達式(Regular Expressions)?
現在,如果知道正則表達式,你可能會認為可以用它來編寫代碼做同樣的事情。當然,我也有過這個問題。我曾使用BeautifulSoup和正則表達式來做同樣的事情,結果發現:
BeautifulSoup裏的代碼比用正則表達式寫的更強大。用正則表達式編寫的代碼得隨著頁面中的變動而進行更改。即使BeautifulSoup在一些情況下需要調整,但相對來講,BeautifulSoup較好一些。
正則表達式比BeautifulSoup快得多,對於相同的結果,正則表達式比BeautifulSoup快100倍。
因此,它歸結為速度與代碼的魯棒性之間的比較,這裏沒有萬能的贏家。如果正在尋找的信息可以用簡單的正則表達式語句抓取,那麽應該選擇使用它們。對於幾乎所有復雜的工作,我通常更多地建議使用BeautifulSoup,而不是正則表達式。
結語
本文中,我們使用了Python的兩個庫BeautifulSoup和urllib2。我們也了解了HTML的基礎知識,並通過解決一個問題,一步一步地實施網頁抓取。我建議你練習一下並用它來從網頁中搜集
用Python進行網頁抓取