美食是人類的畢生追求,說到美食,咱們總會想起美團美食,面對類型衆多的商家,應如何選擇優質的商家,使消費最大合理化。在本 Chat 裏,將講述如何爬取美團商家信息。正則表達式
廢話很少說,咱們直接在瀏覽器打開美團美食的網址,而後打開谷歌的開發者工具,並刷新網頁,從新捕捉請求資源,如圖所示:sql
根據店名在 Network 選項卡的各個分類標籤下查找數據所在的 HTML 源碼位置,在每一個請求信息的 Response 下使用 Ctrl+F 快速查找店名(初漾臺味黑糖),最終在 Doc 標籤下找到相關信息,如圖所示:數據庫
從圖上的信息能夠看到,地址欄的 gz 表明區域「廣州」,全國的美食商家是以城市進行劃分的。而商家的數據是以 JSON 格式表示,網頁上顯示的信息均可以在此找到。在這個網頁中,咱們是要查找這個商家的 URL 地址,從而進入商家詳細頁。瀏覽器
但從美團美食的首頁中,咱們能獲取的信息就這麼多,所以,咱們先訪問店家詳細頁,發現商家詳細頁的 URL 地址帶有一串數字。不一樣的商家,數字內容都不同,如圖所示:markdown
經過對比發現,每一個商家詳細頁的 URL 地址只有末端的數字串是不相同的,這應該是美團給商家標記的 id,咱們取其中一個商家 id 回到美團首頁查找,發現可找到相關信息,如圖所示:網絡
根據上述分析,咱們能夠在美團美食首頁裏獲取商家 id,經過 id 來構建商家詳細頁的 URL 地址。框架
獲得了商家詳細頁的 URL 地址後,下一步是在商家詳細頁裏進行數據爬取。數據爬取分爲兩部分:商家信息和顧客評論,如圖所示:函數
首先,咱們找出商家信息所在的請求信息,在開發者工具的 Network 選項卡的 doc 標籤下找到相關信息,商家信息是在 doc 標籤下找到,而且也是以 JSON 格式表示,如圖所示:工具
接着是分析顧客評論所在的請求信息,最終在 XHR 標籤下找到相關的請求信息,如圖所示:網站
綜合上述,咱們須要從三個請求信息裏獲取數據,三個請求信息的說明以下:
目前只是簡單分析了三個請求信息,每一個請求的請求參數和請求頭會在功能實現的過程當中詳細講解。
根據現有的分析,咱們建立項目文件夾 meituan,項目文件分別有 Insql.py、meishi.conf 和 meishi.py,文件說明以下:
簡單分析網頁後,接下來咱們先實現全部商家的信息爬取。因爲商家詳細頁只須要商家 id 便可,所以爬取全部商家信息只需爬取商家 id 便可。
從美團美食的首頁得知,其 URL 地址的「gz」表明廣州。首頁的底部設有分頁功能,當點擊第二頁的時候,URL 末端新增下級目錄 pn2,第三頁的下級目錄爲 pn3,以此類推,新增的下級目錄表明分頁的頁數。當遍歷 32 次便可獲得當前城市全部美食商家信息,如圖所示:
根據 URL 的變化規律和商家信息的 HTML 源碼結構,全部商家信息的爬取功能定義爲函數 get_all(),函數參數 city_list 表明各個城市信息並以字符串表示,如 gz、bj 等,函數代碼如圖所示:
函數 get_all() 所實現的功能說明以下:
在函數 get_all() 裏,咱們調用了函數 get_info(),它是進入訪問商家詳細頁的,主要爬取商家的基本信息。商家詳情頁的 URL 地址爲 http://www.meituan.com/meishi/%s/,其中 %s 表明商家 id。
注意:若是對商家詳細頁發送 HTTP 請求,這裏涉及了一個反爬蟲機制——Cookies 的使用,咱們查看該請求的請求頭內容。如圖所示:
商家詳細頁的請求頭與通常的請求頭並沒有太大差別,按照以往的開發模式,首先構架 URL 地址,而後對 URL 發送請求,最後從請求裏獲取響應內容並提取目標數據。按照該思路,商家的基本信息爬取功能如圖所示:
當運行程序的時候,程序是沒有提取到商家信息了,這說明該請求的響應內容不是商家詳細頁的網頁內容,確定遇到反爬蟲檢測。在請求頭裏,除了還沒有加入 Cookies 以外,其他屬性已添加,所以,咱們嘗試加入 Cookies,發現能夠提取到商家信息。
可是隻使用一個 Cookies 也會中斷爬取過程,緣由在於訪問頻繁。爲了下降訪問頻繁,引入 Cookies 池,將代碼的請求部分進行修改,以下所示:
從函數 get_info() 裏可到,它調用了函數 get_comment(),並將商家 ID 和 find_uuid 分別傳入,find_uuid 是從函數 get_all()提取出來的數據,這兩個函數參數都是構建顧客評論的 AJAX 接口的請求參數,如圖所示:
所以,函數 get_comment() 的代碼如圖所示:
爬蟲的核心功能大體已實現,接着講解數據存儲方面。數據存儲以 MySQL 爲例,存儲過程使用 ORM 框架 SQLAlchemy,這樣可實現數據持久化,它的優勢此處不一一講述。
首先在 Insql.py 裏導入 ORM 框架 SQLAlchemy,並建立相關對象,經過 SQLAlchemy 鏈接本地 MySQL 數據庫。數據庫編碼設爲 UTF8mb4,由於評論信息裏可能出現手機表情這類特殊內容,這些特殊內容是超出 UTF-8 的編碼範圍。代碼以下:
將商家信息和顧客評論信息分別存儲在數據表 meituan_shop 和 meituan_comment。數據表之間存在一對多的數據關係,一個商家會有多條顧客評論,映射類的定義以下:
上述只是定義映射類,數據存儲的功能還沒有實現。數據存儲由函數 shop_db() 和函數 comment_db() 實現,二者會對待存儲的數據進行判斷,若是數據已存在數據庫,則進行更新處理,反之新增一條數據。代碼以下:
配置文件給爬蟲程序 meishi.py 讀取,用於控制爬蟲的爬取方向,好比爬取北京、上海等城市的美食信息。將配置文件命名爲 meishi.conf,配置信息以下:
配置文件只設置配置屬性 city,屬性值是將每一個城市編號以英文逗號的形式拼接起來,城市編號是首個字母拼音開頭組成的。函數 get_all() 的函數參數 city_list 就是配置屬性 city。
在爬蟲文件 meishi.py 裏,文件運行函數 _main_ 主要讀取配置文件的配置屬性 city,並調用函數 get_all(),代碼以下: