房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。

老貓我在南五環租了一個80平兩居室,租房合同馬上到期,房東打電話問續租的事,想要加房租;我想現在國家正在在抑制房價,房子價格沒怎麼漲,房租應該也不會漲,於是霸氣拒絕了,以下是聊天記錄:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
確認不續租之後,兩三年沒找過房的我上網搜索租房,沒想到出來一坨自如,蛋殼,貝殼等中介網站;進去看看,各種房照非常漂亮,但是一看房租,想送給自己一首《涼涼》;附近房租居然比我當前房租高1000多RMB;自我安慰下,這些網站房源價格不是真實的,於是切換到我愛我家,鏈家等大中介平臺,結果發現房租價格都差不多;心想這才幾年,如果兩年前對自己狠點買了房,房租都夠還房貸了。爲了生存,不甘心的我,決定把這些大網站的房源信息抓取下來進行分析,帝都這麼大總有一套適合自己。

說幹就幹,先找到市場上主要的中介平臺,我主要關注我愛我家、鏈家、貝殼,還有其他類的長租公寓例如自如,蛋殼等;經過查資料還發現一個問題,好像鏈家、貝殼、自如是一個大老闆,鏈家房源和自如的都是混到一起的,整的我一個頭大;而貝殼類似於京東,不僅自己自營,還允許其他中介商來入住這個平臺,這老闆腦瓜子真是好使,折騰半天把數據都掌握在自己手裏,總感覺這些年房價與房租上漲和這個貨有種說不清的關係。

最後決定使用Python抓取鏈家,我愛我家,與貝殼網租房信息。

老貓租住小區門口就有一鏈家,每天西裝革履的經紀人在小區裏晃悠;先從鏈家下手,抓取與分析過程如下:

1:查看鏈家房源信息,決定抓取數據;
2:數據請求行爲分析;
3:分析實現這個功能所使用知識點,
4:抓取代碼實現與調試;
5:對出租房源信息進行分析;

1.使用瀏覽器查看要抓取信息:

藉助瀏覽器打開鏈家主頁,找到租房菜單,查看要抓取信息;
地址:https://bj.lianjia.com/zufang/
頁面信息如下圖:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
從當前信息中可以看到,鏈家有近19000套在線房源(某些爲單間,一些爲北三縣);
根據頁面信息確認抓取信息,主要包括:所屬小區,戶型,面積,價格,所屬區域,具體地址,房齡,房屋編號及詳情頁地址;確認抓取信息後,分析請求行爲,進行抓取。

2.請求行爲分析:

使用瀏覽器打開頁面,查看請求過程,主要分幾步進行抓取:

1> 請求首頁:https://bj.lianjia.com/zufang/
2>解析北京下屬區域對應url,注意:這裏不包括燕郊與香河;
3>按照行區域逐頁抓取並提取頁面房源信息,直到抓取結束;

整個請求過程如下:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
確認抓取過程後,分析抓取過程使用的知識點。

3.知識點分析:

整個抓取過程分爲請求數據,提取信息,數據保存,老貓這邊使用Python實現,主要知識點如下:

1>請求數據:requests模塊;
2>提取信息:BeautifulSoup模塊;
3>數據保存:csv格式存儲,csv模塊;

請求行爲與知識點分析完成後,老貓在Jupyter下完成了單頁數據抓取與信息提取,具體過程這裏不詳細講解,直接上最終代碼。

4.鏈家出租房源信息抓取實現:

老貓使用類實現抓取與信息提取,快速描述實現過程:

1>整理思路,確認要做的事情,分步實現;
2>根據請求與提取行爲定義類與相關方法;
3>將Jupyter下實現填充到對應方法中;
4>存儲類實現;
5>代碼調試與運行;

最終代碼如下:

#coding=utf-8
#Author: qimao

import requests
from bs4 import BeautifulSoup
import json
import csv
import time

class CsvSaveModule(object):
    #存儲csv類
    def __init__(self, fname = "info.csv"):
        self.f = open(fname, 'w', encoding='utf-8')
        self.fcsv = csv.writer(self.f)
        self.head = True

    def write(self, keys, data):
        #寫入字段
        if self.head:
            self.head = False
            self.fcsv.writerow(keys)
        #獲取並寫入數據
        values = [data.get(key, "") for key in keys]
        self.fcsv.writerow(values)

    def close(self):
        self.f.close()

class SpiderMoujia(object):
    def __init__(self, *args):
        'args:保存數據對象'
        self.urlhead = 'https://bj.lianjia.com/'
        self.hds = args

    def reqPage(self, url):
        num = 0
        #一個頁面最多嘗試請求三次
        while num < 3:
            #請求頁面信息,添加請求異常處理,防止某個頁面請求失敗導致整個抓取結束,
            try:
                if url:
                    req = requests.get(url)
                    if req.status_code == 200:
                        #返回BeautifulSoup對象
                        return BeautifulSoup(req.text, 'html5lib')
            except:
                pass
            time.sleep(3)
            num += 1

    def startCrawler(self, url):
        #抓取對外接口,Url爲種子url
        self.startRequest(url)
        self.close()

    def startRequest(self, url):
        #開始抓取
        obj = self.reqPage(url)
        areas = obj.find('div', class_="option-list")
        #提取區域信息:海淀,朝陽,....
        listarea = areas.select('a[href^="/zufang/"]')
        for area in listarea[1:]:
            aurl = self.urlhead + area.get('href')
            district = area.text.strip()
            #按照區域進行抓取
            self.crawlerArea(aurl,district)

    def crawlerArea(self, url, district):
        #print('crawlerArea', url)
        page = self.reqPage(url)
        if not page:
            return
        #解析頁面信息
        self.parsePage(page,district)
        #獲取下一頁地址
        nextpage = self.getNextPage(page)
        if nextpage:
            urlhead = url.rsplit('/',1)[0]
            nexturl = '/'.join([urlhead, nextpage])
            #繼續請求下一頁
            self.crawlerArea(nexturl,district)

    def extractInfo(self, node, css):
        snode = node.select_one(css)
        val = ''
        if snode and snode.text:
            val = snode.text.strip()
        return val

    def parsePage(self, page,district):
        #主要功能,提取頁面信息
        listhouse = page.select('#house-lst > li')
        #定義出提取字段
        keys = ['信息', '小區', '戶型', '價格', '面積', '區域',
                '位置', '樓層', '年份', '附加信息', '房屋ID', '詳情頁地址']
        for house in listhouse:
            hinfo = []
            #提取title, 小區,戶型,價格,面積
            cssexpress = ['h2 a', '.where a', '.zone', '.num','.meters']
            info = house.select_one(".info-panel")
            if not info:
                continue
            for express in cssexpress:
                hinfo.append(self.extractInfo(info, express))
            #添加區域
            hinfo.append(district)
            #區域,樓層,年代
            hinfo.extend(info.select_one('.con').text.split('/'))
            #房子其他信息,例如:地鐵,陽臺,供暖等
            spans = info.select_one('.view-label')
            hpoint = ','.join((spans.stripped_strings))
            hinfo.append(hpoint)
            #房子ID號,唯一標識
            hinfo.append(house.get('data-id'))
            #房租詳情頁url
            hinfo.append(info.select_one('h2 a').get('href'))

            #轉換成字典
            housedata = dict(zip(keys, hinfo))
            print (housedata)
            self.saveData(housedata)

    def getNextPage(self, page):
        try:
            #獲取下一頁
            pagenode = page.select_one('.page-box')
            pageinfo = pagenode.get('page-data')
            jdata = json.loads(pageinfo)
            curpage = jdata.get('curPage')
            total = jdata.get('totalPage')
            if (curpage < total):
                return 'pg%d'%(int(curpage+1))
        except:
            print('error')
            pass

    def saveData(self, data):
        #按照順序保存數據
        keys = ['信息', '小區', '戶型', '價格', '面積', '區域',
                '位置', '樓層', '年份', '附加信息', '房屋ID', '詳情頁地址']
        [hd.write(keys, data) for hd in self.hds]

    def close(self):
        #列表解析關閉存儲模塊
        [hd.close() for hd in self.hds]

if __name__ == '__main__':
    #開始抓取
    url = 'https://bj.lianjia.com/zufang/'
    csvhd = CsvSaveModule('ljinfo.csv')
    spider = SpiderMoujia(csvhd)
    spider.startCrawler(url)

運行過程如下圖:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
最終獲取了1W多套出租房信息,到這裏我完成鏈家出租房源信息抓取。

5.我愛我家與貝殼抓取分析。

我愛我家是一個老牌的房地產中介,老貓來帝都10年了,畢業當年大部分同學幹了當年認爲比較正統的工作,一個另類同學去了我愛我家做中介,早些年他經常羣裏發消息,給我們介紹房源,大家認爲他是推銷,很少有人理他;最近同學聚會見面我問他:你當年爲什麼不在使勁逼着我買房?同學擡起頭,吸了一口煙吐了一圈,說了一句話,讓我感覺夏天頓時涼爽了許多:'逼你你也買不起,逼你你也買不起,逼你你也買不起,重要事情說三遍',感覺友誼的小船就要翻了。
下面我們來看我愛我家出租房源頁面信息,如下圖:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
從頁面中我們可以看到,我愛我家有3.2萬套出租房源,房源信息比較直觀;通過分析發現抓取我愛我家請求行爲與抓取鏈家類似,不同之處在於提取數據與提取過程;我們可以在基於鏈家爬蟲進行修改實現;具體實現過程在這裏不詳細講解,直接上抓取部分結果:

區域,地址,小區,價格,面積,樓層,裝修,地鐵附近,戶型,朝向,信息,附加信息,詳情
朝陽,望京,寶星國際,8000,64  平米,低樓層/25層,精裝,距離地鐵望京東450米,1  室  1  廳,南,寶星國際緊鄰望京SOHO 阿里巴巴  精裝朝南大開間,"近地鐵,隨時看,拎包入住,押金減免",/zufang/41330436.html
朝陽,望京,炫彩嘉軒,6500,60  平米,中樓層/21層,精裝,距離地鐵望京東760米,1  室  0  廳,南,炫彩一居室老業主委託 我有鑰匙 鄰望京SOHO,"近地鐵,可短租,拎包入住,集中供暖",/zufang/41348206.html
朝陽,望京,寶星國際,8500,64  平米,高樓層/25層,精裝,距離地鐵望京東450米,1  室  1  廳,南北,望京SOHO旁寶星國際,鄰阿里巴巴,綠地,南向大開間,"近地鐵,隨時看,拎包入住,押金減免",/zufang/41331126.html
朝陽,CBD,陽光100國際公寓,9500,48  平米,低樓層/33層,精裝,距離地鐵大望路391米,1  室  1  廳,北,陽光100國際公寓精裝開 二次裝修有鑰匙看房方便,"近地鐵,隨時看,免傭,拎包入住",/zufang/41330729.html
朝陽,望京,朝庭公寓,13000,112  平米,高樓層/27層,精裝,距離地鐵望京南476米,2  室  1  廳,南北,望京南朝庭公寓,鄰悠樂匯和方恆國際,看房有鑰匙,隨時看房,"近地鐵,隨時看,免傭,拎包入住",/zufang/41337320.html
朝陽,石佛營,日月東華,6700,66.3  平米,頂層/21層,精裝,距離地鐵十里堡1072米,1  室  1  廳,南,石佛營新上婚房一居拎包入住 看房預約,"近地鐵,拎包入住,集中供暖",/zufang/41348814.html
朝陽,惠新西街,勝古北里,2800,58  平米,底層/5層,精裝,距離地鐵惠新西街南口232米,3  室  1  廳,北,隨時看 隨時住三家合住正規中臥室精裝修,"近地鐵,隨時看,拎包入住,集中供暖",/zufang/41338276.html
朝陽,潘家園,弘善家園,5300,61  平米,中樓層/13層,精裝,距離地鐵十里河691米,1  室  1  廳,南,十里河 潘家園10號線 弘善家園精裝正規一居 拎包入住,"近地鐵,拎包入住",/zufang/41334177.html
朝陽,東壩,朝陽新城一區,6500,114  平米,中樓層/6層,精裝,,2  室  1  廳,南北,朝陽新城一區兩室一廳,隨時看,/zufang/41351101.html
朝陽,十里堡,十里堡,6000,60  平米,底層/4層,中裝,距離地鐵十里堡781米,2  室  1  廳,南北,6號線 十里堡 南北兩居帶小院子 居家必備,"近地鐵,隨時看,集中供暖",/zufang/41345370.html
朝陽,十里堡,十里堡北里,5000,50  平米,中樓層/13層,中裝,距離地鐵十里堡371米,1  室  1  廳,南北,十里堡 八里莊北里 晨光家園  隨時看,"近地鐵,免傭",/zufang/41342158.html
朝陽,南沙灘,南沙灘小區,7000,65  平米,中樓層/6層,精裝,距離地鐵北沙灘775米,2  室  1  廳,南北,南沙灘 中間層兩居室 臨地鐵北辰中科院 有鑰匙,"近地鐵,隨時看,拎包入住",/zufang/41341943.html
朝陽,管莊,管莊周井大院,6000,72  平米,中樓層/5層,精裝,距離地鐵雙橋604米,3  室  1  廳,南北,管莊周井大院精裝三居室出租 隨時入住,"近地鐵,隨時看,拎包入住,集中供暖",/zufang/41339579.html
朝陽,百子灣,金泰先鋒,10000,92  平米,底層/11層,精裝,距離地鐵百子灣437米,2  室  1  廳,南北,金泰先鋒 南北兩室一廳一廚一衛,"近地鐵,拎包入住,集中供暖",/zufang/41328442.html
朝陽,北苑,蘊實園,5800,66.37  平米,中樓層/14層,精裝,距離地鐵北苑571米,1  室  1  廳,南,鑰匙房源,看房隨時。,"近地鐵,隨時看,拎包入住",/zufang/41349514.html
朝陽,芍藥居,芍藥居,13000,118.38  平米,中樓層/14層,簡裝,距離地鐵芍藥居116米,3  室  1  廳,南,芍藥居南里精裝修三室一廳,"近地鐵,隨時看,拎包入住,集中供暖",/zufang/41348855.html
朝陽,雙橋,東一時區,4500,65  平米,中樓層/26層,精裝,距離地鐵管莊1214米,1  室  1  廳,西北,管莊 東一時區 精裝一居室 家電齊全 隨時入住看房,"近地鐵,拎包入住,集中供暖",/zufang/41346286.html
...

最後我們來看貝殼抓取,貝殼是近些年起來的中介平臺,有點類京東,不僅有鏈家,自如房源,還有其他家;除了貝殼,還有其他很多短租長租平臺,例如小豬短租,蛋殼等;
有時候我常思考一個問題:

負能量:這些網站都是IT開發人員搞得,我們都是一個行業,爲什麼要自己坑自己。如果沒有這麼多中介平臺去搶房源,炒房價,價格可能落下來;
正能量:中介商根據市場需求搭建中介平臺,使廣大租客可以從正規渠道租房,遠離黑中介,給我們省去很多租房過程中遇到難題與煩惱,我們應該感謝這些中介商。

下面我們看下貝殼網頁面信息:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
貝殼房源信息中除了基本信息,還包括房源屬於哪個中介商,例如:自如,鏈家等;貝殼抓取過程和鏈家也是類似的,具體實現在這裏不做講解,直接看我們抓取的數據:

中介商,價格,面積,信息,區域,位置,戶型,樓層,附加信息,詳情頁地址
鏈家,14000,84㎡,整租 · 海運倉小區 3室1廳 14000元,東城,東直門,3室1廳1衛,低樓層(7層),"近地鐵,精裝,集中供暖",/zufang/BJ2058598225715675136.html
鏈家,9200,89㎡,整租 · 安定門 安德路 精裝修大兩居 可拎包入住,東城,安定門,2室1廳1衛,高樓層(19層),"近地鐵,精裝",/zufang/BJ2047499309347512320.html
鏈家,6000,61㎡,整租 · 安化南里 1室1廳 6000元,東城,廣渠門,1室1廳1衛,低樓層(16層),"近地鐵,新上,隨時看房",/zufang/BJ2062732570394894336.html
鏈家,3500,14㎡,整租 · 南剪子巷 1室1廳 3500元,東城,東四,1室1廳0衛,低樓層(1層),"近地鐵,新上,隨時看房",/zufang/BJ2064894449783685120.html
鏈家,25000,158㎡,整租 · 東城逸墅南北通透大三居 婚房出租 可看房 傢俱齊全,東城,工體,3室1廳2衛,中樓層(7層),"近地鐵,精裝,集中供暖,雙衛生間,隨時看房",/zufang/BJ2034641117466591232.html
城家精選公寓,11300,43㎡,整租 · 元嘉國際公寓 1室0廳,東城,東直門,1室0廳1衛,未知(10層),"公寓,租房節,七天換租,近地鐵,精裝,集中供暖,免中介費,押一付一,新上",/zufang/BJ2066558104174067712.html
鏈家,28000,207㎡,盛德大廈 4室2廳 28000元,東城,和平里,4室2廳2衛,中樓層(20層),"近地鐵,集中供暖,隨時看房",/zufang/BJ2049715273455910912.html
龍源易家,3500,26㎡,合租 · 海運倉小區 3室1廳,東城,東直門,3室1廳1衛,未知(6層),"限女生,限男生,獨立衛生間,租房節,近地鐵,精裝,獨立陽臺,集中供暖,免中介費,新上",/zufang/BJ2066335711790891008.html
...

房源信息抓取完成後保存到csv文件中,然後對數據進行分析,找到適合自己的那一套。

5.房源價格分析:

老貓算了下,三個平臺數據加起來差不多7W套左右(鏈家數據和貝殼有重複,同一個房源可同時掛在不同中介商下),所有應該到不了7W套。
老貓使用Python中的matplotlib, pandas, seaborn, pyecharts對數據進行分析。

5.1 鏈家各區房源數量,最高價,最低價,均值統計:
#pandas導入文件
pathlj = ljinfo.csv'
ljdata = pd.read_csv(pathlj)
#按區域分組
r = ljdata.groupby('區域')
#根據價格統計最大、最小、均值、數量
r.價格.agg(['max', 'min', 'mean', 'count'])

結果如下:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。

使用柱狀圖描述各區房源數量與均價:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。

在來分析下鏈家,貝殼與我愛我家各區域房源統計結果:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
通過統計結果可以看到:我愛我家房源比鏈家,貝殼要多,假設房源都是真是的,如果要在朝陽,海淀租房可以選擇我愛我家。

5.2 分析北京各轄區出租房源的價格分佈:

當前數據中,出租房源參差不齊,面積價格都不一樣,不能統一統計,通過箱狀圖看房租價格統計,具體實現如下:

#文件路徑
pathlj = 'ljinfo.csv'
#pandas導入
ljdata = pd.read_csv(pathlj)
#過濾掉房租價格大於1W的,老貓認爲這輩子也不會租這樣的房
data = ljdata[ljdata.價格 < 10000]
plt.figure(figsize=(10,4))
#箱狀圖查看房租價格整體趨勢
sns.boxplot(x='區域',y ='價格', data=data)

輸出結果:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。

簡單介紹下箱狀圖:箱狀圖使用四分位數表述數據分佈情況,中間矩形表示25%到75%之間數據分佈,超過上限和下限認爲是異常值;
再來看我愛我家與貝殼統計結果,如下圖:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。

從圖中可以看到帝都核心區域房租明顯比郊區高很多,東城最低房源價格都得兩千多,亦莊雖然在五環外,但是因爲是開發區,有很多大公司入住,所有房價較高;房源選擇上,我愛我家價格感覺比其他兩個平臺要高。

現在我對北京租房價格有了全新認識,我主要想找70到85平左右小兩居,需要找到各區這個面積範圍內房源及其對應價格,我對鏈家數據進行下面操作:

import re
#數據整理,將字符串轉成數字
def func(size):
    s = re.search(r'\d+', size)
    if s:
        return int(s.group())
    return pd.np
#pandas導入數據
pathlj = 'jinfo.csv'
ljdata = pd.read_csv(pathlj)
data = ljdata.面積.to_frame()
#整理面積數據
r = data.applymap(func)
#添加新的列
ljdata['hsize'] = r.面積
#清洗無面積房源
rdata = ljdata.dropna(subset=['hsize'])
#整理70~85平米之間房源
rdata = rdata[(rdata.hsize>70) & (rdata.hsize < 85)]
#過濾掉價格大於1W的房源
rdata = rdata[rdata.價格<10000]
#統計最小值,最大值,均值
rdata.價格.agg(['min', 'max', 'mean'])

輸出結果如下:

min     2500.0
max     9890.0
mean    5997.4

經過分析,老貓感覺3000左右可以租到想要的房子,然後統計各個轄區內房源面積在70~85平之間的價格分佈,結果如下:
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
核心區域價格確實高,老貓想找大興和亦莊開發區附近房子,價格好像超出老貓預算,我租住房屋面積75,房租3100,房東加800也纔不到4000,根據分析結果看,找4000左右的兩居室感覺也沒那麼容易;再找一下大興和亦莊開發區的房子,具體實現如下:

tdata = rdata[rdata.區域.isin(['大興','亦莊開發區'])]
#大興與亦莊房子數據
print(len(tdata))
#房源均價,最低,最高值
print(tdata.價格.agg(['mean', 'min', 'max']))
#房源價格小於4000
print(len(tdata[tdata.價格<4000]))

輸出結果如下:

109
mean    4907.889908
min     3100.000000
max     9000.000000
21

找到21套價格小於4000房源,看下房源信息,多是老舊樓,或者高樓層沒電梯,好容易有合適的,打電話諮詢,已經租出去了;鏈家都已經這樣了,估計我愛我家,貝殼也類似。
思前想後,感覺還是現在房東最好,趕緊給她聯繫續租,以下聊天記錄。
房東要漲800房租,我用Python抓取帝都幾萬套房源信息,主動漲了1000。
這波漲租潮,對老貓來說就這樣過去了,看着滿屏幕房源信息,我不知道明年房租是否還會瘋長;現在老貓的租房競爭對手不僅是衆多北漂,還有實力更爲雄厚的自如、蛋殼等各種中介商,爲了生存,今年必須要更加努力了。


最後打個小廣告,有對爬蟲和數據分析感興趣同學可以購買奇貓的專欄《Python爬蟲與數據分析》

另外,如果感覺還行可以關注奇貓的視頻課程或者微職位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章