暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

做了个Python爬虫,爬取深圳新房预售价格表

非资深老网工 2021-04-02
964

深圳住建局官方网站 http://zjj.sz.gov.cn/ris/bol/szfdc/index.aspx 会公示新房预售价格信息。但是如果要找到套房的户型、面积、单价等信息,非常麻烦。因为每个套房的信息都放在了一个单独的页面,而且藏得很深,要点进去 4 层:项目 > 楼栋 > 单元 > 套房。



如上图所示,如果一个项目有 1000 套可售套房,就要点开 1000 个网页。另外,住建局只提供了建筑面积单价,需要自己计算总价。



@咚咚找房 会提供新房价格表,但需要交 9.9 元会员费。他们的价格表虽然信息很全,但看起来非常不直观,不方便。微博上的 @唐老师傅 提供的价格表就很给力。https://weibo.com/10890189


前段时间终于治好了自己的拖延症,写了第 1 个 Python 脚本,用来选择 ETF 基金。我想,把 @唐老师傅 的价格表作为自己的第 2 个练手项目应该挺合适的。用了几天,终于写完并且修好了bug。现在这个脚本可以抓取所有项目,包括办公、公寓、住宅、商铺,也适配地下层和区局锁定状态。手工简单修改一下自动生成的 result.xlsx ,就可以得到 result_manual_optimization.xlsx,和 @唐老师傅 的表格差不多。


当然,我这脚本虽然管用,但其实挺简陋的,没用 Scrapy 框架,有一些库的工作原理我也没搞明白。所以现在肯定不会厚着脸皮在这里谈怎么写 Python。我想扯点别的经验😁😁


经验 1,就是要动手,越早越好。


Python 是一种语言,所以学习方法应该和学英语是一样的。靠每天背单词学不会英语,靠上 Python 课学各种库各种工具的使用方法也学不会 Python,必须要多用才行。前些年我还在 Coursera 上参加了一门课程,写了几个游戏。最后写的一个游戏是打飞机,特酷。感觉回到了红白机时代。



但是游戏的框架是教授提供的,要写什么库,要写什么函数,每个函数的功能,也都是教授确定的。所以虽然把游戏写出来了,但要是自己写个东西,还是一样抓瞎。抓瞎了就畏惧写东西,不写东西慢慢就忘光了。所以这就引出第 2 个经验,就是编程的思路。


经验 2,要熟悉业务流程,要拆解任务。


前些天在读《我的第一本算法书》的时候,里面有一句话很关键:


计算机擅长高速执行基本命令,但无法执行复杂的命令

非资深老网工,公众号:非资深老网工《我的第一本算法书》读书笔记


所以要把一个大任务拆解成若干个小任务。为每个小任务写一个函数就对了。当然,还得搞清楚,如果要完成最终任务,需要怎样的业务流程。这也是售前工程师的基本功。确定了业务流程,就确定了各个函数之间的调用关系,那么,写程序的思路自然就出来了。


就拿这个爬虫程序来讲,根据 URL 抓取 HTML 页面是一个任务;在“套房详细信息”页面抓取楼栋、楼层、房号、面积、单价是一个任务;在单元页面抓取所有套房的 URL 是一个任务;在楼栋页面抓取所有单元的 URL 是一个任务;在项目页面抓取所有楼栋的 URL 是一个任务...这样一环套一环,就能一步一步地完成最终的任务。


只有思路还不行,还得把思路落实到代码上。这就引出第 3 个经验,勤用 Google,广泛借鉴他人的代码。


经验 3,要积极地抄袭借鉴别人写的代码。


将思路落实到代码的过程需要了解具体的 Python 语法,具体的第三方库和函数的使用方法。初学者的知识储备不足是很正常的,如果总是想等着把所有的 Python 工具的使用方法都学会再写程序,那黄瓜菜都凉了。所以要擅用 Google,看看为了实现某个功能,别人是怎么写的,然后把他的代码搬过来。


比如我的爬虫脚本,整体的框架是模仿知乎用户 @憨憨 的文章:

https://zhuanlan.zhihu.com/p/192774611

(也正是因为读了 @憨憨 的文章,才有了写爬虫的勇气。这说明选择难度合适的学习材料是多么重要。这算是经验 4 吧,哈哈)很多其他的代码也是东拼西凑过来的。


抄袭不是一件好事。郭敬明于正都道歉了,对吧。但模仿和借鉴没有错。本来人家就是开源的,你搬过来,消化成自己的,然后同样也开源出去不就行了么。反正咱也没有商业化的意图,也不挡人财路。也不要担心自己的代码烂,不敢开源。初学者脸皮就要厚一点,学东西都要有个过程。


第 5 个经验,要试图成为一个优秀的产品经理


在梳理业务流程的时候,在写代码的过程中,要时刻思考:你的最终的任务目标是不是正确的?你想要输出的最终数据是不是合理的?


因为现在深圳新房限价,开发商为了提高利润,就在户内面积不变的情况下做大建筑面积。结果看上去单价不高,似乎有很多倒挂,但如果计算户内单价,就会发现价格高的吓人。比如大冲的某网红盘,120 平方米户型的户内单价是 19 万,99 平方米户型的户内单价 17 万多,已经超过香港的房价了。所以我开始就想着要做一个比 @唐老师傅 信息更全的表格,单价、总价、得房率、户内单价都可以在同一个表格里面看到。但如果要实现这样的功能,程序会变得非常复杂,远远超过了我的能力。写代码的工作也无法进行下去了。


但程序复杂不复杂,并不是问题的关键。问题的关键是,购房者真的在乎每一个套房的得房率和户内单价吗?其实他们不在乎,或者知道一个大概的总体的情况就行了。


所以 @唐老师傅 成功是必然的,他是一个优秀的产品经理,抓住了读者的痛点。而我则犯了“既要,又要,还要”的错误。


想清楚这个问题之后,事情就变得很简单,利用 10 行左右的 Pandas 代码就搞定。


最后一个经验,测试!测试!特么测试!


这句话其实是我的一位前同事,一位编程大牛在朋友圈发出的怒吼。我深以为然。每写完一个函数,都要测试看看它返回的结果是不是你想要的,数据类型对不对,数据格式是不是符合预期。然后再写下一部分。


这里推荐一个测试工具:pysnooper 


虽然用print也不失为是一种方法,但是有时如果疑惑的地方多就要每个地方都要加print,这样就显得比较麻烦了。Github开源了一个神器---PySnooper,允许和print执行相同的操作,只需向感兴趣的函数添加一个装饰器行,而不是小心地创建正确的打印行。将会得到函数的详细日志,包括运行了哪些行、何时运行、以及何时更改了局部变量。

QIAN,公众号:CU技术社区Python: 告别Print?优秀的Debug神器---pysnooper


写完程序之后,还得多跑几遍,在多种场景下观察程序返回的结果是否都是正确的。我根据一个住宅项目写完爬虫之后,用这个爬虫跑了十几个新房预售项目。不跑不知道,一跑才知道有多坑。有的新房项目的套房按照数字编号,有的按照英文字母编号;有的新房项目没有“单元”,有的项目按照“单元”划分,有的先按照“座”来分,然后再按照“单元”来分。


有的套房处于“区局锁定”状态,没有价格。写字楼项目更加坑,座号直接就是一个数字,一层楼有二三十间房,还有地下层的商铺。


只有充分的测试,才能发现这些 bug,然后修复之。


以上,就是我作为一个编程老白,到目前为止总结的经验。让各位见笑了。我的爬虫项目地址:

https://github.com/chenghit/crawler_for_SZZJJ

欢迎编程大牛帮忙优化。



文章转载自非资深老网工,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论