likes
comments
collection
share

为了买房,我抓取了某家房源的成交数据(实战篇)

作者站长头像
站长
· 阅读数 11

一、缘起

上文说到,自从2022年加入看房大军,在咨询中介并被推荐一些不是很满意的房源后。秃然的,一个奇怪的想法在脑中诞生了

为何不做一套监控房源价格的系统呢?

二、简单介绍

该篇为【实战篇】,主要讲解的是如何实现房源监控的流程,也涉及到分析、代码编写等相关细节

【分析篇】详见:为了买房,我抓取了某家房源的成交数据(分析篇)

本实战采用的编程语言是Java,框架是Spring,当然语言并不重要,重要的是思想,所以其它语言的小伙伴也可放心观看,我在描述中也会尽量降低语言相关性

为了买房,我抓取了某家房源的成交数据(实战篇)

为了降低部署的复杂度,采用了内置的SQLLLite数据库,用于保存抓取的房源数据。当然,这也不重要,你也可以用txt文件保存,这都是行得通的(我第一版做的就是用txt文件保存的)

本篇实战重点讲述实现思路,并不打算做成通用的工具,因此本篇文章重点在于渔,而非鱼。

三、效果展示

为了买房,我抓取了某家房源的成交数据(实战篇)

Github: github.com/yz19930826/…

四、前置准备

工欲善其事必先利其器,先介绍下使用到的工具,当然可以不着急下载,但是我必须得先介绍下,来展示下我的博学与多才

4.1、http/https请求工具

我用的是postman ,抓到数据包后,用它可以伪造一个请求发过去看看效果。

如下图,如此我们就可以随意的改变参数,来观察接口的返回值

为了买房,我抓取了某家房源的成交数据(实战篇)

postman下载地址请戳:戳我戳我,我是官方下载地址

4.2、抓包工具

我这里使用的是lightproxy,或者常用的fiddler均可,大家根据自己爱好随意选用,熟悉哪个用哪个

lightproxy的官方下载地址请戳:戳我戳我,我也是官方下载地址,进去后根据自己的操作系统进行选择,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

五、功能逻辑分析与实现

5.1新上架房源监控

5.1.1逻辑分析

什么是新上架的房源?新上架的房源指的是和某个时间点在售的房源相比,多出来的房源。举个例子,如下图

为了买房,我抓取了某家房源的成交数据(实战篇)

比如昨天查询出来的房源有两个,今天查询出来的房源有三个,经过对比,就可认定4150w的房源为新上架的房源。

所以需要三步:

  1. 需要保存昨天的在售房源
  2. 需要查询今天的在售房源
  3. 两者对比

当然这里的查询时间粒度由大家自己把控,可以一天查询一次进行对比,也可五分钟查询一次进行对比

下面就聊聊这些点

5.1.2 小区在售房源查询

首先打开抓包工具,抓取Http请求,我这里使用的是lightproxy,如下图

为了买房,我抓取了某家房源的成交数据(实战篇)

进入某家网站,大大的搜索框映入眼帘,输入小区名称,点击开始找房

为了买房,我抓取了某家房源的成交数据(实战篇)

为了买房,我抓取了某家房源的成交数据(实战篇) 在LightProxy中会自动抓取本次操作所有的Http请求,一番查找即可找到小区房源查询的接口,如下图

为了买房,我抓取了某家房源的成交数据(实战篇) 可见,查询当前小区在售房源的接口是:https://bj.lianjia.com/ershoufang/rs%E5%8D%97%E6%B5%B7%E5%AE%B6%E5%9B%AD/,这里对中文进行了url编码,随便找个在线url编码解析的网站解码下,如下,最终的结果是:https://bj.lianjia.com/ershoufang/rs南海家园/

为了买房,我抓取了某家房源的成交数据(实战篇) 如果小区房源较多,会出现分页的情况,如下:

为了买房,我抓取了某家房源的成交数据(实战篇)

这时候只需要点击下第二页,同上步骤,得到接口如下:https://bj.lianjia.com/ershoufang/pg2rs南海家园/,这样即可推导出接口分页的规律,即第三页为:pg3rs南海家园,第n页为:pgnrs南海家园

此外,该接口返回的数据是Html格式的,因此还需要对HTML进行解析一下,得到感兴趣的数据

我用的是Java语言,对Html的解析有工具包拿来即用,有兴趣的可以看下:jsoup.org/,其它语言基本也都封装好的工具包,可以找找

5.1.2.1 伪代码实现

为了更清晰的说明逻辑,这里只贴了伪代码,Javaer可以参考github,类全路径为:com.gogobuy.houseDA.manage.LianJiaWebApi#communitySellingHouse

以下涉及到代码的部分均同理


int pageNo = 1;

while(true){
  
  // 调用Http接口获取数据
  String result = http.get("https://bj.lianjia.com/ershoufang/pg +"pageNo"+rs南海家园/");
  
  // 解析Html,获取房源信息
  List<String> houseCodeList = getHouseDataFromResult(result);

  // 房源信息为空,跳出循环
  if(houseCodeList.isEmpty()){
    break;
  }
}

这里用while(true)的原因是在小区房源多的情况下,是分页展示的,因此需要多次调用分页API获取数据,当查询的数据为空时,证明小区房源已查询完,跳出循环

举个例子,如下图,当前小区房源总共有5页,如果访问第6页,其接口为:https://bj.lianjia.com/ershoufang/pg6rs南海家园/,那么返回的房源数据即为空,这也就说明该小区的房源只有5页

为了买房,我抓取了某家房源的成交数据(实战篇)

5.1.3 房源数据保存

抓取到的房源数据保存在sqllite数据库中,sqllite数据库的特点是小巧,无需部署,资源占用低,非常适合这个场景

如下图所示,sqllite数据库集成在了工程目录下,直接上传到github上

为了买房,我抓取了某家房源的成交数据(实战篇)

需要注意的是,相较于常用的mysql来说,sqllit的数据类型有些差别,具体如下:

  1. NULL:空值。
  2. INTEGER:整型,可以存储带符号的或无符号的整数值,占用 1、2、3、4、6、8 字节。
  3. REAL:实数,用于存储带有小数的数字,占用 8 字节。
  4. TEXT:字符串类型,用于存储字符串或文本数据,占用 N 个字节,N 最大为 2^31-1,即2GB。
  5. BLOB:二进制数据类型,用于存储二进制数据,占用 N 个字节,N 最大为 2^31-1,即2GB。

保存的数据如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

5.1.4 对比

对比找出新上架的房源信息,这个比较简单,直接贴伪代码

// 从接口中获取小区在售房源的信息
List<HouseData> houseList = getSellingHouse("南海家园");

// 遍历房源,若在数据库中不存在,则认为该房源为新增的房源,然后将其保存到数据库
for(HouseData hs : houseList){
  if(!inDb(hs)){
    // 保存到数据库 该房源即可认为是新增的房源
    storeToDb(hs);
  }
}

值得注意的是,第一次访问时,数据库里是没有房源数据的,那么所有在售的房源都可以认为是新增的房源

以上逻辑在github上全路径为:com.gogobuy.houseDA.job.LianJiaHouseWatchJob#newHouseDataWatchProcess

5.2 停售房源监控

5.2.1 逻辑分析

在某家网站和app上,关注房源后,若房源下架会有通知,房源状态会变为【已停售】,我们就可以利用这个功能特性,在关注房源后不断的扫描关注房源的状态并和在数据库的房源信息比对,若发现关注列表房源为停售,且数据库房源为在售,则可认为房源状态变更为停售

为了买房,我抓取了某家房源的成交数据(实战篇)

举个栗子:

为了买房,我抓取了某家房源的成交数据(实战篇) 如上图,关注的房源和数据库房源分别有俩,分别是大别野1号院和大别野2号院,当调用某家接口获取关注的房源数据和数据库对比时,发现大别野2号院状态变更为停售,而数据库依然是在售状态时,则证明大别野2号院停售了

获取关注的房源需要登录,下面介绍下登录态的获取

5.2.2 登录态

如何获取登录态以及在后续的请求中附带上登录态信息是本节需要聊聊的内容

先聊聊这些网站或APP是如何做身份验证的

和身份证类似,在我们登录成功后,系统会为我们颁发一个身份证明,通常是一串数字或字符串,名称有的叫uuid,uid,token,sessionid,whatever,都不重要

在后续的请求中,带上这个身份证明,就认为是已经登录成功的状态,如下

为了买房,我抓取了某家房源的成交数据(实战篇)

举个例子,如下为某家登录页

为了买房,我抓取了某家房源的成交数据(实战篇) 在我们点击登录之后会请求登录接口,登录成功后在会将身份证明写到Cookie中,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

这么多的cookie不知道哪个是身份证明的怎么办?很简单,小孩子才做选择,我全都要,如下图,找一个登录之后请求的接口,复制所有的header

为了买房,我抓取了某家房源的成交数据(实战篇) 然后拿这个header利用postman工具请求获取关注房源的接口,如下图所示,得到了正确的返回信息

为了买房,我抓取了某家房源的成交数据(实战篇)

若不放cookie的话,返回的就是让去登录的页面,也就是无法验证请求者的身份

为了买房,我抓取了某家房源的成交数据(实战篇)

5.2.3 关注房源的查询

我们可以从WEB和APP两个渠道获取关注的房源信息,从WEB渠道比较简单,但是由于我上次抓到数据后和某家的销售嘚瑟了一下,过几天发现Web渠道的房源成交价不展示了!如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

这样的话我们只能从难度较高的APP端来获取关注的房源数据了,这部分内容在【已售房源监控】进行说明

为了买房,我抓取了某家房源的成交数据(实战篇)

5.3 已售房源监控

5.3.1 逻辑分析

在关注房源后,若房源成交,会在关注的房源列表看到已成交的房源信息以及房源价格

不同的是成交价的获取,之前网站是有漏出成交价的,但是由于我实现后的嘚瑟,导致某家屏蔽网站上的成交价了,只在APP上对成交价漏出,如下图,这里的540.6w实际上就是成交价,而非挂牌价

为了买房,我抓取了某家房源的成交数据(实战篇) 但APP端使用了数据做了签名,导致没办法篡改请求,简单介绍下签名认证

签名认证就是将发送的数据按照一个某个算法计算出一个密文,在请求接口的时候将密文和数据同时发送给服务端进行验证,服务端拿到数据后按照相同的算法计算出密文和传输来的密文进行对比,若不一致,则丢弃请求

举个例子,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇) 小秃的手机登录了某家APP想要查询北京南海家园的房子信息,在输入了相关的搜索条件后,点击了搜索

某家APP利用签名算法计算出该请求数据的签名信息,和参数信息拼接在一起都发给某家服务器

某家服务器拿到参数后,利用相同的签名算法计算出签名信息后,和APP传输来的签名信息进行对比,若一致,则请求合法,若不一致,则拒绝请求

因此,在我们拿到接口后,想更改参数信息,比如我想查询北海家园的房源数据,将query修改北海家园,因此不知道签名算法,就无法生成签名信息,在服务端进行签名比对时就失败了。

除非,反编译某家APP获取签名算法,但这会令我少数的头发雪上加霜,这部分就留给大家解决了

为了买房,我抓取了某家房源的成交数据(实战篇) 但这就没什么办法了吗?有的有的,下面着重介绍传说中的“暴力”遍历法

5.3.2 APP端关注房源的查询

既然不让篡改信息,那就不篡改,某家APP限制只能关注200个房源,每页显示20条数据,那么最多只需要10次就可以get到所有关注的房源信息,所以我们需要抓这10个请求的查询参数及签名信息,然后原封不动的再发送请求即可

为了买房,我抓取了某家房源的成交数据(实战篇) 如下图,保存了10个获取关注房源的API信息以及对应的Header信息(签名信息是在header中的):

为了买房,我抓取了某家房源的成交数据(实战篇)

为了买房,我抓取了某家房源的成交数据(实战篇)

5.3.3 伪代码实现

// 遍历10个接口
for(int i = 0 ; i < 10 ; i ++){
  // 带上原header请求api,获取关注的房源信息
  String result = http.get(api[i],header[i]);
  // 为空的话跳出,因为我们关注的房源数据不一定有10页
  if(result.isEmpty()){
    return;
  }
  // 解析房源信息
  HouseData houseData = parseHouseDataFromResult(result);
}

github上的Java实现:

com.gogobuy.houseDA.manage.LianJiaAppApi#queryFollowedHouseData

6.1 变动通知

这里做的是邮件通知,因为免费

我用的是163邮箱往QQ邮箱发邮件,然后在微信上绑定了QQ邮箱邮件通知,这样微信上就可以收到通知了,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

6.1.1 如何用代码发送邮件?

一般邮箱可以开启SMTP(Simple Mail Transfer Protocol)协议,SMTP是一种用于发送邮件的协议。它定义了邮件客户端如何将邮件发送给邮件服务器,并通过邮件服务器进行中转和传递到目标邮件服务器。

我们可以申请一个163邮箱,然后开启SMTP协议,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇) 利用Java代码发送邮件,使用的是hutool的工具包,参考文档,hutool.cn/docs/#/extr…

hutool的配置,如下图:

为了买房,我抓取了某家房源的成交数据(实战篇)

此部分代码实现:com.gogobuy.houseDA.notice.EmailNotice#send

六、成果展示

经过上面的一番操作,意向小区的房源信息对我来说更加的透明,于是便拿到了红皮书...

为了买房,我抓取了某家房源的成交数据(实战篇)

七、总结

本文讲述了如何抓取某家APP的步骤及流程,总得来说,需要的知识点还是比较繁琐的。

在实战中分析,在实战中学习是最好的方式

当然如果要买房最好的方式还是找个靠谱的经纪人问问,如何判断是否靠谱,总结了一下方法论,几个问题问问即可,让经纪人感受下八股文的魅力

  • 第一:小区的价格区间是多少(涉及小区户型,楼层、装修等细节)
  • 第二:目标户型的市场价大约多少?(最近6个月哪个楼层和楼栋成交价是最高的,哪个楼层和楼栋成交价是最低,价格差距主要体现在什么地方)
  • 第三:目标小区成交量近几个月大约多少?哪个户型成交量最高,(涉及小区历史成交情况和市场热度)

任何疑问留言,另外大家对文章描述有什么建议,都可在此说说,一方面有助于降低后续文章的阅读难度,一方面也可以提高我的文笔,,如果觉得文笔和内容还行,那就点赞关注支持下喽

下集预告「为了省钱,我做了一款查券公众号」

效果图如下:

为了买房,我抓取了某家房源的成交数据(实战篇)