您现在的位置是:首页 > 文章详情

房东要涨800房租,我用Python抓取帝都几万套房源信息,主动涨了1000。

日期:2018-08-25点击:419

老猫我在南五环租了一个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爬虫与数据分析》

另外,如果感觉还行可以关注奇猫的视频课程或者微职位。

原文链接:https://blog.51cto.com/huangyg/2164433
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章