1. 程式人生 > >Python爬蟲一步步抓取房產資訊

Python爬蟲一步步抓取房產資訊

嗯,這一篇文章更多是想分享一下我的網頁分析方法。玩爬蟲也快有一年了,基本程式碼熟悉之後,我感覺寫一個爬蟲最有意思的莫過於研究其網頁背後的載入過程了,也就是分析過程,對效能沒有特殊要求的情況下,程式設計一般是小事。

以深圳地區的X房網為例吧。XX房網的主頁非常簡潔,輸入相應的地區就可以找到對應的二手房或者一手房。這一篇文章主要就給大家介紹我在做XX房網爬蟲的分析過程。

注意:本文采用Chrome作為分析載入工作,如果使用其他瀏覽器,請參考具體的規則。 
首先想到的

嗯,你首先要跳出程式設計,從使用者甚至是產品經理的角度去思考:在瀏覽這個頁面的時候,如何就能看到全市的二手房的情況。通過主頁的一個區一個區的輸入,搜尋,然後將頁面的單元下載,嗯這是一個方法。

南山區首頁的情況

如 上圖所示,只要更改keyword後面的引數,就可以獲得不同區的二手房資料。程式設計的時候只需要手動寫入一個含有各個區的list,然後通過迴圈去更改 keyword後面的引數,從而開始一個區域,再爬取其中的連結。這個方法確實是可行的,深圳一共也沒有多少個區。這個方法我試過是可行的。

我實際想說的

上面的這個方法固然可行,但並不是我想推薦的方法,大家看回首頁,搜尋欄旁邊有一個地圖找房。點進去你就能看到深圳全區域的房子,要是能在這裡弄個爬蟲,不就簡單多了。

地圖找房位置

深圳全區域的二手房

可以看到截圖的右側有所有二手房的連結,我們的任務就是下載右邊的所有二手房的資料。首先第一步就先檢視頁面的原始碼(Ctrl+U),可以從右邊連結串列那裡 複製一些關鍵字,在原始碼裡面找找看,在原始碼裡面Ctrl+F搜尋觀瀾湖試試,結果是沒有,再嘗試幾個關鍵詞好像都沒有,但通過檢查元素 (Ctrl+Shift+I),是可以定位到這些關鍵詞的位置。這樣可以初步判斷右邊的連結串列是通過Js來載入,需要證實。

關鍵詞觀瀾湖的在原始碼裡面的搜尋結果

關鍵詞觀瀾湖的在頁面元素裡面的搜尋結果

嘗試對觀瀾湖上方的元素在原始碼裡面定位,例如no-data-wrap bounce-inup dn,就可以在原始碼裡面找到。仔細對比一下兩邊的上下文,可以看到在節點下面的內容有非常大的差異。通過這個roomList作為關鍵詞繼續查詢。

no-data-wrap bounce-inup dn 在檢查元素內的位置

no-data-wrap bounce-inup dn 在原始碼的位置

在檢查元素裡面可以發現roomList下面的載入的內容就是我們所需要的房屋列表,並且這部分內容再原始碼裡面沒有。而在原始碼頁通過搜尋roomList,卻發現出現在script裡面,證實roomList裡面的內容是通過Js來載入的:

原始碼中roomList出現的位置

下面就變成是找這個roomList了,由於是通過js載入的,開啟控制檯的network,並重新重新整理頁面,檢視頁面裡面各個元素的載入過程,在過濾器裡面輸入roomList,可以找到一條資訊:

roomList的搜尋結果

點 開看response裡面下載的內容,發現那不就是我們要找的東西嗎!裡面有給出詳細的頁面數量(roomPageSize),那一個個的八位數字顯然就 是每一個房子的id嘛,然後每一頁的載入數量是一定的,下面有對應id裡面有房子的經緯度、戶型、面積以及朝向等等資訊(在這裡做一個提醒,需要做 heatmap的同學注意了,這裡的經緯度用的是百度座標,如果你後續視覺化用的是google地圖、高德或者GPS,是需要轉換座標的)。

roomList的內容

找到內容之後,接著就是看他的Headers,看看是如何載入的。

  • Request Url表明其訪問的連結,Request Method表明他的請求方法是Post;

  • Request的頭定義(Headers)裡面包括Host、Origin、Referer、User-Agent等;

  • 請 求的引數(parameters)裡面有三個引數,這三個引數是直接放映在其Url連結上面,裡面包括當前頁的頁碼(currentPage)、頁面大小 (pageSize)以及s(這個s一開始也不同清楚是什麼,但是發現每一次請求都有變化,後面才知道這個是時間戳,表示1970紀元後經過的浮點秒 數);

  • 此外Post函式還可以傳送資料到伺服器做請求,這裡所傳送的資料包括始末經緯度、gardenId(這個到後期發現是對應的小區編號)和zoom(代表地圖上面放大以及縮小的倍數,數字越大,放大倍數越高)

Header第一頁

Herader第二頁

基本扒到這裡,對整個頁面就比較清晰了,也知道我們的爬蟲要怎麼去寫了。 
開始寫程式碼了

邏輯整理出來後,整個程式碼就寫的非常輕鬆了。首先通過post方式訪問shenzhen.XXfang.com/map,通過正則表示式提取Reponse裡面的roomPageSize,或者最大頁數。然後對每一頁的內容進行爬取,並將資訊輸出。

第一部分,載入庫,需要用到requests, bs4, re, time(time是用來生成時間戳):

from bs4 import BeautifulSoupimport requests, re, time

第 二部分,通過設定合理的post資料以及headers,通過post下載資料。其中payload裡面包括地圖所展示的經緯度資訊(這個資訊怎麼獲得, 在X房網頁面上通過滑鼠拖拉,找到合適的位置之後,到控制檯Header內檢視此時的經緯度就好了),headers則包含了訪問的基本資訊(加上有一定 的反爬作用):

頁面下載後,對於第一次下載首先需要用正則表示式獲得最大頁面數,我們真正需要的內容結合Beautiful的get和find以及re來抓取就可以了:

給一個在控制檯裡面輸出的效果:

最後的效果

最後,這篇文章給出了我在寫X房網爬蟲的整個分析的思路。

-----------------------------------------

Python中文開發者的精神家園

Garfield_Liang,Python中文社群專欄作者。

-----------------------------------------

-----------------------------------------