程序員租房妙招,爬一個(gè)好房
背景
春節(jié)過(guò)后回京,本想好好休息兩天結(jié)果家里迎來(lái)了不速之客——老鼠。***通過(guò)一系列的操作終于成功捕獲一家 8 口,這個(gè)過(guò)程筆者就不做多描述了。由于此次捕鼠事件留下陰影決定搬離。和媳婦開(kāi)始尋找合適的房源,這還只是一個(gè)開(kāi)始;之后看好房子(房子還在配置中)跟管家約定好釋放當(dāng)日簽約;和媳婦兩臺(tái)手機(jī)兩臺(tái)電腦搶房子結(jié)果還是失之交臂。就算是雙十一也不過(guò)如此吧!
之后繼續(xù)找房發(fā)現(xiàn)基于小區(qū)搜索房源結(jié)果很不準(zhǔn)確(用地鐵站能過(guò)濾出來(lái)的,但直接用小區(qū)名就是搜不全),再加上想對(duì)當(dāng)前市場(chǎng)房源有一個(gè)更清晰的了解,于是便有了一個(gè)想法——能否通過(guò)爬蟲(chóng)自己做個(gè)檢索來(lái)找房子。
開(kāi)始
通過(guò)爬蟲(chóng)自己做個(gè)檢索來(lái)找房子,有了這個(gè)想法后就試著做一下,首先有一個(gè)大概思路:
- 寫(xiě)一個(gè)爬蟲(chóng)程序,盡可能解析出房子相關(guān)信息作為字段存儲(chǔ)。
- 將數(shù)據(jù)存放在 ES(Elasticsearch)中便于查找。
- 使用 kibana 實(shí)現(xiàn)查詢和分析,因其作為 ELK 經(jīng)典組件,在查詢分析上的強(qiáng)大優(yōu)勢(shì)不再多言。
需開(kāi)發(fā)的爬蟲(chóng)可分為如下模塊:
- 控制模塊:作為起始開(kāi)關(guān)和任務(wù)管理
- 抓取模塊:輸入一個(gè)網(wǎng)址,輸出網(wǎng)頁(yè)內(nèi)容
- 解析模塊:接收一段內(nèi)容,輸出有價(jià)值的字段信息,以及下一頁(yè)等更多待解析的任務(wù)
- 存儲(chǔ)模塊:簡(jiǎn)單的做一個(gè) map 進(jìn)行運(yùn)行時(shí)去重,然后將信息寫(xiě)入 ES
整個(gè)架構(gòu)和其他爬蟲(chóng)基本一樣,但自如為防止爬蟲(chóng),搜索結(jié)果最多顯示50頁(yè),對(duì)應(yīng)辦法就是遍歷重要的查詢參數(shù),比如城市、地鐵站、房子類型等。于是解析模塊的順序大概是:
1. 城市列表解析器,用來(lái)解析不同城市(當(dāng)然這里只需要北京)
2. 地鐵站解析器,用來(lái)解析出不同的地鐵站
3. 房屋列表解析器,用來(lái)解析每一頁(yè)的房屋列表和下一頁(yè)待解析的任務(wù)
4. 房屋詳情解析器,用來(lái)解析房屋的詳細(xì)信息,如朝向、面積、戶型、樓層、陽(yáng)臺(tái)、室友等
這里需要注意幾點(diǎn):
1. 爬蟲(chóng)使用 golang,它本身沒(méi)有解析庫(kù),可以用第三方的 css 樣式選擇器、xpath,也完全可以用正則搞定,這里主要用正則實(shí)現(xiàn),部分地方試用了下 css 選擇器。
2. 部分房間信息如地鐵站、地鐵線路、所屬 url、陽(yáng)臺(tái)、裝修風(fēng)格在房屋詳情中不容易提取,可以在上一級(jí)頁(yè)面如房屋列表中獲得。
3. 房租價(jià)格做了反爬蟲(chóng)處理,不容易獲得,具體是價(jià)格為不同圖片拼接,這些圖片根據(jù)一個(gè)靜態(tài)隨機(jī)頁(yè)面搭配 offset 進(jìn)行判斷,然后通過(guò) ocr 進(jìn)行基本圖片識(shí)別就能得到。
在上一級(jí)的網(wǎng)頁(yè)源碼中可以發(fā)現(xiàn)對(duì)應(yīng)的原始圖片和序號(hào),這樣就很簡(jiǎn)單了。
接下來(lái)是圖片識(shí)別,需要用到一個(gè)利器——tesseract(https://github.com/tesseract-ocr/tesseract/wiki)
盡管有這么個(gè)神器,但解析成功率依然不能保證 100%,尤其是在沒(méi)有訓(xùn)練的情況下,因此就需要像上面代碼中那樣,在短期內(nèi)想提高效率就添加部分人工識(shí)別的代碼,并降低重復(fù)工作,也能基本滿足需求。
接下來(lái)是寫(xiě)入存儲(chǔ),這里為快捷實(shí)現(xiàn),我們用 docker 在本機(jī)運(yùn)行 es 和kibana,如下:
需要注意:盡量使用高版本,5.6 以后的 es 鏡像版本中都默認(rèn)安裝了 x-pack 并激活了基礎(chǔ)版本的 license(即免費(fèi)使用基礎(chǔ)功能,在這里也夠了)golang 對(duì)接 ES 可以使用官方的 client。代碼如:
注意上面的 setSniff=false,如果不加會(huì)有如下報(bào)錯(cuò):
在docker中運(yùn)行es時(shí),默認(rèn)啟動(dòng) sniffing 模式,es自動(dòng)查找節(jié)點(diǎn), 要確保 Elasticsearch 返回可從容器外部訪問(wèn)的 IP 地址。
解決方式為關(guān)閉 sniffing 或者配置 es 返回的主機(jī)地址,參考https://github.com/olivere/elastic/wiki/Docker
1. 配置 elasticsearch
- 將 network.publish_host 和 network.bind_host 配置為可從容器外部訪問(wèn)的地址
- 配置network.host (不用再單獨(dú)配置network.bind_host 和 network.publish_host)
2. 禁用 sniffing
elastic.SetSniff(false)
最終,經(jīng)過(guò)一番嘗試,登錄 kibana 開(kāi)始新的探索:
比如,基于多條地鐵線進(jìn)行房源查找,甚至可以排除部分職業(yè)的室友,舉個(gè)栗子,排除下自己。
然后在 kibana 的 Visualize 中進(jìn)行更多的分析:
比如最貴的地鐵站周邊和地鐵線周邊,2號(hào)線因?yàn)槭莾?nèi)環(huán)地鐵線路,均價(jià)毫無(wú)爭(zhēng)議***。地鐵站圓明園算是景區(qū)之外,中關(guān)村最貴也合情理。整租方面因?yàn)殡p井附近有一些豪宅而略高,其他地區(qū)基本在9500左右。
市場(chǎng)行情:
整租6-7k最多,合租費(fèi)用上2-3k則是***頻,其次是3-4k,而我也總算知道為什么之前的房源那么搶手了,因?yàn)樗犬?dāng)?shù)鼐鶅r(jià)低了500多;而1500以下的為數(shù)不多的幾個(gè)都在遠(yuǎn)郊。
房源的情況:
可以看到大部分自如客住的都在20平內(nèi),占比約76%,如果細(xì)分的話可以看到10-15是***比的,而10號(hào)地鐵線的房源最多。
房源最多集中在頂樓,這些多數(shù)是沒(méi)電梯的老樓;而帶獨(dú)立陽(yáng)臺(tái)的,則只有20%;而從朝向上看,雖然南的比例***,但非南的加起來(lái)也遠(yuǎn)超它,可見(jiàn)大多數(shù)人都和陽(yáng)光處的不太好。
從租客信息可知,男女比例相差不多,但星座上天秤座卻比射手多好些。而從職業(yè)上看,IT行業(yè)(開(kāi)發(fā)研發(fā)、測(cè)試、運(yùn)維)占比遠(yuǎn)比其他要高,而他們又最多分布在8號(hào)線和13號(hào)線(西二旗表示很淡定自如)。
關(guān)于季節(jié):
2月份是過(guò)去一年的高峰期,大量的人合同到期,也有大量的人重新簽約,這里涉及到無(wú)數(shù)個(gè)小家的遷入和遷出,無(wú)數(shù)個(gè)打包和解包,無(wú)數(shù)個(gè)的——重新開(kāi)始!
經(jīng)過(guò)一番折騰,新房也找好了,等著過(guò)陣子搬過(guò)去。總結(jié)之后,生活還是要繼續(xù),也許還會(huì)在新家遇到老鼠,也一定會(huì)再隨著生活變遷而搬到其他地方,但在這次“折騰”里,我得以用另一個(gè)視角去看自己,看待我和群體的關(guān)系,看待我們和這座城市的關(guān)系,以便更好的選擇我們的未來(lái)。
注意:
以上只是個(gè)人基于部分?jǐn)?shù)據(jù)所得做的簡(jiǎn)單分析,無(wú)法保證精確。
爬蟲(chóng)應(yīng)在不對(duì)目標(biāo)服務(wù)器產(chǎn)生較大干擾的情況下操作,可通過(guò)channel+time.Tick 進(jìn)行主動(dòng)限速。