豆瓣上有不少租房小組,每個小組都有自己的房源。對要尋找租房信息的用戶來說,到各個小組中去查找的合適的房源信息,需要花很長的時間和精力。筆者也正是遇到這樣的問題,於是寫了個程序自動收集各個租房小組的房源,提供統一查詢功能。另外,當有合適的新房源發佈後,筆者希望第一時間接到房源上線通知,畢竟好房源大家都搶著要,早一刻聯繫房東多一點機會租道合適的房子。
先上圖,讓大家看看效果。大家也可以上www.qianxuzufang.com/wx瀏覽。每個房源包含以下信息:
標題
發佈時間
圖片
房源詳細描述
原文鏈接
戶型
租金
房東聯繫方式
接下來介紹如何從豆瓣中抓取這些信息。首先需要分析一下豆瓣網頁結構,我需要抓取的網頁其實就只有兩個。第一個是租房小組的房源列表頁面。舉個例子看這個租房小組:https://www.douban.com/group/279962/, 分析其頁面結構,如下圖:
上圖看到的是在Chrome開發調試模式下打開豆瓣小組的效果,左側是瀏覽器中的展示效果, 右側是HTML源碼。這個頁面非常整齊,每條房源記錄都是<tr class="">開頭,</tr>結束。
使用parseHouseList函數,我們就能獲取一個房源信息的列表,list中每一個元素都是一條房源記錄的原始信息, 如下圖:
房源原始信息裡面包含:房源標題,鏈接,發佈時間,發貼人信息等。同樣的,我們可以用獲取房源列表的方法來提取這些信息。
接下來我們要抓取的就是房源的詳細信息頁了,其結構如下圖:
抓取房源詳細信息的時候使用html-to-text這個npm包,它可以幫從房源描述信息中去除我們不需要的html標籤,把html源碼直接轉成文本。抓取圖片url的方法與之類似,不再累述了。
到目前為止,我們已經能抓取房源標題、發佈時間、詳細信息、房源鏈接和圖片了。剩下的房租、戶型和房東聯繫方式等信息是無法用上面的方法抓取的。我們需要分析標題和房源詳細信息,從中提取一下模式,然後使用正則表達式來抽取這些信息。
上圖是使用正則表達式提取房租信息的代碼,使用正則表達式的關鍵是要學習提取模式。同樣的可以用下面的正則表達式提取聯繫方式、戶型等信息。
const phoneNumberPatt=/((手機|電話)(:|:|\s)?(\s)?(1[3|5|7|8|][0-9]{8}))/;
const snsPatt=/((微信|qq|QQ)號?(:|:|\s)?(\s)?([\d\w_一二兩三四五六七八九零]{5,}))/;
const areaPatt=/(\d{1,3})(多)?[平|㎡]/;
const modelPatt=/(([\d一二兩三四五六七八九])[居室房]([123一二兩三]廳)?([12一二兩]廚)?([1234一二兩三四]衛)?([12一二兩]廚)?)/;
到目前為止,我們已經能提取所有我們想要的信息了。但實際操作中,我們可能會遇到一些其他問題,需要注意:
出了豆瓣外,我們還可以抓取58同城,趕集網等的個人房源信息,總之越多越好。
如果房源比較多,為了提高抓取效率,可以使用多線程並行抓取。Node.js天生的事件機制非常適合並行抓取。
豆瓣有反爬蟲機制,如果我們短時間內請求數目太多的話,會上豆瓣的黑名單,導致無法繼續抓取房源。解決辦法:
i. 控制Node.js並行抓取的數目
ii. 設定好抓取頻率,如每10分鐘抓取一次,可以改為每小時抓取一次
iii. 使用多機多ip輪流抓取
同一套房源在多個小組發佈時,我們並不希望看到它在查詢結果中出現多次,需要聚合這些房源。
如何保存這些房源信息,提高查詢效率?
查詢結果比較多時,該如何對這些房源進行排序呢?
用戶查詢‘清華大學’時,可能想看周邊的房源,我們是不是能給用戶推薦‘五道口’的房源呢? (注:清華大學和五道口離的很近,故清華大學又被稱為五道口男子技院)
如何自動識別過濾中介發佈的房源?
關於上面這些問題,我將在以後的文章陸續介紹相應的解決辦法。請大家多多支持。
最後如果大家想體驗或使用上面的租房信息搜索引擎的話,可以關注微信公眾號:千尋租房;或訪問網站:http://www.qianxuzufang.com/wx