前言
數據爬蟲就是通過代碼的形式對于網絡上的數據進行爬取,例如獲取成都近3年的空氣質量數據,如果通過人工收集則太過低效了。所以我們必須借助代碼來實現。
數據爬蟲主要有兩種方式
- 通過網站提供的API進行爬取。
這是最為簡單直接的方式,例如豆瓣網提供了對于電影、書籍等資源的各種數據的API,我們可以通過調用API來得到所需的數據。通過API的缺點是有些網站會限制API調用的次數和頻率,用戶需要付費來升級成高級用戶來獲取更靈活的API調用。 - 基于HTML的數據抓取
這個方法比較麻煩,優點就是不受API的調用限制。通過訪問網頁的HTML代碼,并從中抓取到所需節點上的數據。這個方法還有一個缺點就是,網頁一旦發生一點小小的結構變化,抓取代碼就有可能需要重寫。
這篇文章中我們將討論第一種方式。并將以豆瓣電影API為例子實現數據的抓取。
安裝Jupyter Notebook
Jupyter Notebook是一個交互式的筆記本,可以理解成是一個IDE,支持40多種語言,而我們將用它來編寫Python程序。Jupyter Notebook用起來非常的方便,而且各大數據挖掘類的比賽所使用的文件格式基本都是Jupyter Notebook的。
首先我們在命令行當中使用如下命令打開Python環境,命令中的python36
是我們之前配置的Python運行環境的名字,具體如何設置請參考【大數據】環境配置 。
source activate python36
使用Conda來安裝Jupyter Notebook:
conda install jupyter
打開Jupyter Notebook:
jupyter notebook
隨后瀏覽器會被打開,我們會發現Jupyter Notebook是一個嵌入在瀏覽器當中的編輯器,用起來非常方便。
然后我們找到一個合適的文件位置,點擊右上角的New按鈕,選擇新建一個Python 3的Notebook。這時瀏覽器會打開一個新窗口,顯示一個剛剛創建的Notebook。這時我們可以在文本框中輸入Python代碼了。
豆瓣API
在這篇文章中我們將嘗試通過Python代碼來訪問豆瓣電影的API,來抓取一些豆瓣上歷史評分最高的20部電影的分數。首先我們可以訪問豆瓣電影Api文檔閱讀相關信息。這里我們可以看到,為了實現我們的目的我們需要兩組接口:v2/movie/top250
用來獲取歷史評分最高的20部電影的ID(其實這里已經包含了評分,出于學習目的我們只從中讀取電影ID信息)以及/v2/movie/subject/:id
通過電影ID來獲取電影的具體信息。
通過Python代碼訪問豆瓣API
首先這里我們先引入一個urllib
的包來發送http請求。
import urllib.request as request
然后訪問豆瓣電影Top250的API用來獲取評分最高的20部電影的信息。并通過print函數將內容輸出。
url = 'https://api.douban.com/v2/movie/top250'
crawl_content = request.urlopen(url).read()
print(crawl_content)
從截圖中我們發現已經有一些我們可以閱讀的內容了,但是如何將這些內容提取出來呢?其實這一段內容是一段JSON格式的信息,我們可以通過將其格式化讓其變得更具可讀性。引入json
工具包并用它對crawl_content
進行格式化。
import json
print(json.loads(crawl_content.decode('utf8')))
此時我們發現內容更加具有可讀性,比如這一次請求拿回的條目一共有20條,全部在subjects節點下面。現在我們就可以通過一層一層的節點訪問拿到評分最高的20部電影的ID,然后在通過豆瓣電影API去拿到每一部電影的具體信息。
如果我們只想得到片名和評分之間的一個對應關系,我們可以深入到相應的節點上進行爬取。代碼如下:
import urllib.request as request
import json
url = 'https://api.douban.com/v2/movie/top250'
crawl_content = request.urlopen(url).read()
top20 = json.loads(crawl_content.decode('utf8'))['subjects']
for movie in top20:
url = 'https://api.douban.com/v2/movie/' + movie['id']
movieContent = request.urlopen(url).read()
print(json.loads(movieContent.decode('utf8'))['title'] + ': ' + json.loads(movieContent.decode('utf8'))['rating']['average'])
這樣我們就通過訪問API的方式爬取到了我們所需要的數據。