首頁>科技>

前言

/file/2019/11/28/20191128233654_6939.jpg 爬取 “得到” App 電子書資訊

“得到” App 是羅輯思維出品的一款碎片時間學習的 App,App 內有很多學習資源。不過 “得到” App 沒有對應的網頁版,所以資訊必須要通過 App 才可以獲取。這次我們通過抓取其 App 來練習 mitmdump 的用法。

爬取目標

我們的爬取目標是 App 內電子書版塊的電子書資訊,並將資訊儲存到 MongoDB,如圖所示。

我們要把圖書的名稱、簡介、封面、價格爬取下來,不過這次爬取的側重點還是了解 mitmdump 工具的用法,所以暫不涉及自動化爬取,App 的操作還是手動進行。mitmdump 負責捕捉響應並將資料提取儲存。

2. 準備工作

請確保已經正確安裝好了 mitmproxy 和 mitmdump,手機和 PC 處於同一個區域網下,同時配置好了 mitmproxy 的 CA 證書,安裝好 MongoDB 並執行其服務,安裝 PyMongo 庫,具體的配置可以參考第 1 章的說明。

3. 抓取分析

首先探尋一下當前頁面的 URL 和返回內容,我們編寫一個指令碼如下所示:

def response(flow): print(flow.request.url) print(flow.response.text)

這裡只輸出了請求的 URL 和響應的 Body 內容,也就是請求連結和響應內容這兩個最關鍵的部分。指令碼儲存名稱為 script.py。

接下來執行 mitmdump,命令如下所示:

mitmdump -s script.py

開啟 “得到” App 的電子書頁面,便可以看到 PC 端控制檯有相應輸出。接著滑動頁面載入更多電子書,控制檯新出現的輸出內容就是 App 發出的新的載入請求,包含了下一頁的電子書內容。控制檯輸出結果示例如圖 所示。

可以看到 URL 為 /file/2019/11/28/20191128233654_6940.jpg 的介面,其後面還加了一個 sign 引數。通過 URL 的名稱,可以確定這就是獲取電子書列表的介面。在 URL 的下方輸出的是響應內容,是一個 JSON 格式的字串,我們將它格式化,如圖 所示。

格式化後的內容包含一個 c 欄位、一個 list 欄位,list 的每個元素都包含價格、標題、描述等內容。第一個返回結果是電子書《情人》,而此時 App 的內容也是這本電子書,描述的內容和價格也是完全匹配的,App 頁面如圖所示。

這就說明當前介面就是獲取電子書資訊的介面,我們只需要從這個介面來獲取內容就好了。然後解析返回結果,將結果儲存到資料庫。

4. 資料抓取

接下來我們需要對介面做過濾限制,抓取如上分析的介面,再提取結果中的對應欄位。

這裡,我們修改指令碼如下所示:

import jsonfrom mitmproxy import ctx def response(flow): url = '/file/2019/11/28/20191128233654_6940.jpg' if flow.request.url.startswith(url): text = flow.response.text data = json.loads(text) books = data.get('c').get('list') for book in books: ctx.log.info(str(book))

重新滑動電子書頁面,在 PC 端控制檯觀察輸出,如圖所示。

控制檯輸出

現在輸出了圖書的全部資訊,一本圖書資訊對應一條 JSON 格式的資料。

5. 提取儲存

接下來我們需要提取資訊,再把資訊儲存到資料庫中。方便起見,我們選擇 MongoDB 資料庫。

指令碼還可以增加提取資訊和儲存資訊的部分,修改程式碼如下所示:

import jsonimport pymongofrom mitmproxy import ctx client = pymongo.MongoClient('localhost')db = client['igetget']collection = db['books'] def response(flow): global collection url = '/file/2019/11/28/20191128233654_6940.jpg' if flow.request.url.startswith(url): text = flow.response.text data = json.loads(text) books = data.get('c').get('list') for book in books: data = {'title': book.get('operating_title'), 'cover': book.get('cover'), 'summary': book.get('other_share_summary'), 'price': book.get('price') } ctx.log.info(str(data)) collection.insert(data)

重新滑動頁面,控制檯便會輸出資訊,如圖所示。

現在輸出的每一條內容都是經過提取之後的內容,包含了電子書的標題、封面、描述、價格資訊。

最開始我們聲明了 MongoDB 的資料庫連線,提取出資訊之後呼叫該物件的 insert() 方法將資料插入到資料庫即可。

滑動幾頁,發現所有圖書資訊都被儲存到 MongoDB 中,如圖所示。

目前為止,我們利用一個非常簡單的指令碼把 “得到” App 的電子書資訊儲存下來。

程式碼部分

import jsonimport pymongofrom mitmproxy import ctxclient = pymongo.MongoClient('localhost')db = client['igetget']collection = db['books']def response(flow): global collection url = '/file/2019/11/28/20191128233654_6940.jpg' if flow.request.url.startswith(url): text = flow.response.text data = json.loads(text) books = data.get('c').get('list') for book in books: data = { 'title': book.get('operating_title'), 'cover': book.get('cover'), 'summary': book.get('other_share_summary'), 'price': book.get('price') } ctx.log.info(str(data)) collection.insert(data)

最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 順豐降到4元1單!正式宣戰“三通一達”!網友:這是要拼命了?