利用高德API++Python解决租房问题
一、课程介绍
1. 课程背景
课程来自一段租房血泪史(夸张):事情是这样的,笔者是接着念大四准备考研,而室友是应届毕业在找工作,说白了就是都没有钱,于是打算合租。因为穷所以不可能找有门店的的中介,只能看看赶集、58、和一些租房APP。期间需要考虑两个人的通勤范围来选地段,由于对交通的不熟悉,只有选择自己附近的较贵的地段,花了很多时间阅览赶集或者58里的个人房源信息,然而个人房源信息中仍充斥着大量中介,抱着一点希望打了几个电话,得到的回答都是这个价位根本租不到,再高点也租不到(大都与发布的房源信息不符)。最后终于还是在宿舍关闭前一个星期租到一个性价比还可以的隔断。毕竟隔断还是不方便的,所以打算在室友找到工作后换一个新地方,于是就有了这个租房脚本和课程。
相信也有不少的应届毕业生可能会遭遇同样的境况,希望这门课能真的帮到大家,也许不光是在租房子方面。推荐阅读知乎上的一个问题:你有哪些用计算机技能解决生活问题的经历?
总结一下租房难的症结:
没钱。
小中介发布的价位一般都是假的,会浪费你很多时间。
对交通路线不熟悉以致于选择面窄。
如果是多人,得同时考虑多人的通勤时间。
本课程将解决的问题:
学习了技术,增长了知识,就能找到好工作,找到好工作就能有钱。
这次选的房源信息来自58的品牌公寓馆,所以没有那种小中介,价位就我和我室友来说可以接受。其实可以做个分类器过滤赶集上的中介来找低价个人房源的,有需要的同学可以试一下。
通勤范围在地图上圈出,解决了对交通路线不熟悉的问题
本课程是单人版的,但代码中只要删掉一个语句就能当多人用了(但是路径规划的功能是只能给一个人用)。如果是直接拿来多人用的话,还是开多个页面比较好。
最终效果图如下:
由于没做前端兼容,导致右上角崩了。自用的小工具其实也不用整多好看,效率第一。
如图,划出来的大片蓝***块就是距离工作地点一小时车程内的区域。蓝色的标记就是房源,点击后会自动给出路径规划和房源地址。红色标记(不是"终")是工作地点,在图里被挡住了。工作地点的输入框有自动补完的功能,也是很方便的。至于房源文件我们会通过编写Python脚本在抓取房源信息后生成。
2. 课程知识点
本课程项目完成过程中,我们将学习:
requests、BeautifulSoup、csv 等库的简单使用
高德地图 Javascript API 的使用
二、实验环境
打开终端,进入 Code 目录,创建 rent_proj 文件夹, 并将其作为我们的工作目录。
$ cd Code $ mkdir rent_proj && cd rent_proj
安装需要的库:
$ sudo apt-get install python-bs4
三、实验原理
实验中会用到三个文件:crawl.py,rent.csv与index.html,其中rent.csv由crawl.py生成,是房源文件。crawl.py是一个非常简单的爬取网页的脚本。index.html是最重要的显示地图的部分。实现的流程大致如下:
我为什么不把js代码和css代码从index.html中分出来呢,写脚本怎么顺手怎么来就好。
代码没有难度,主要就是看看几个API如何使用,下面给出文档链接:
高德 JavaScript API 帮助文档
高德 JavaScript API 示例中心
Requests: HTTP for Humans
Beautiful Soup 4.2.0 文档
csv — CSV 文件的读写
四、实验步骤
1. 分析页面
先分析一下我们需要爬取的页面:http://bj.58.com/pinpaigongyu/
选择好目标价位:
打开查看器:
审查元素,分页上的 1 2 3 4 5 随便选一个:
大致了解了它的路径规则:/pingpaigongyu/pn/{page}/minprice={min_rent}_{max_rent}
对比第一页和第一千页:
经过观察,决定将页面有无.list元素来作为是否已读取完所有房源的判断条件。
看一下页面能够提供给我们什么信息:
框框圈出的信息对我们来说已经足够了。当然房源的具体经纬度也可以点进去查看代码得到:
简便起见每一个房源就只记录以下信息:[房源名称,地址,月租,房源url地址]。
其中地址直接取房源名称里的小区名,有的房源第二列是公寓名而不是小区名,那就只能取第一列作为地址了,有些公寓如果合并第一列第二列地图上会搜不到。
2. 编写Python脚本
在工作目录下创建crawl.py文件,这里先直接给出全部代码。
#-*- coding:utf-8 -*-from bs4 import BeautifulSoupfrom urlparse import urljoin import requests import csv url = "http://bj.58.com/pinpaigongyu/pn/{page}/?minprice=2000_4000"#已完成的页数序号,初时为0page = 0csv_file = open("rent.csv","wb") csv_writer = csv.writer(csv_file, delimiter=',')while True: page += 1 print "fetch: ", url.format(page=page) response = requests.get(url.format(page=page)) html = BeautifulSoup(response.text) house_list = html.select(".list > li") # 循环在读不到新的房源时结束 if not house_list: break for house in house_list: house_title = house.select("h2")[0].string.encode("utf8") house_url = urljoin(url, house.select("a")[0]["href"]) house_info_list = house_title.split() # 如果第二列是公寓名则取第一列作为地址 if "公寓" in house_info_list[1] or "青年社区" in house_info_list[1]: house_location = house_info_list[0] else: house_location = house_info_list[1] house_money = house.select(".money")[0].select("b")[0].string.encode("utf8") csv_writer.writerow([house_title, house_location, house_money, house_url]) csv_file.close()
鉴于爬的量不大所以就简单处理了。
csv一般用作表格文件,直接用文本编辑器打开也可读,行与行之间就是换行来隔开,列与列之间就是用逗号(也可指定其它字符)隔开,Python标准库中的csv库就是用来读写csv文件的。
这里只需要写csv文件:
#导入csvimport csv# 打开rent.csv文件csv_file = open("rent.csv","wb") # 创建writer对象,指定文件与分隔符csv_writer = csv.writer(csv_file, delimiter=',') # 写一行数据csv_writer.writerow([house_title, house_location, house_money, house_url])#关闭文件csv_file.close()
requests是一个对使用者非常友好的http库,看一遍Quickstart就能基本掌握它的使用。
用到它的地方也就仅仅两句:
# 抓取目标页面response = requests.get(url.format(page=page)) # 获取页面正文response.text
Beautiful Soup是一个用来解析html或者xml文件的库,支持元素选择器,使用起来也非常方便:
# 创建一个BeautifulSoup对象html = BeautifulSoup(response.text) # 获取class=list的元素下的所有li元素house_list = html.select(".list > li") # 得到标签包裹着的文本house.select("h2")[0].string.encode("utf8") # 得到标签内属性的值house.select("a")[0]["href"]
由于读取到的链接路径是相对路径,所以需要urljoin得到完整的url地址。
urljoin(url, house.select("a")[0]["href"])
实验楼环境中文粘贴进去会变成???,这样的话几个公寓房源的位置就不能确定了,不过不影响做实验。
讲解完毕,运行代码python crawler.py:
可能要1分半钟,可以先去玩一局扫雷。
笔者用自己的电脑跑差不多是20多秒。
此时目录下已生成了rent.csv:
注意如果你太频繁地抓取页面IP可能会被屏蔽,那样就抓不到页面而是直接报错了。如果抓取不成功的话,可以使用这个文件继续接下来的实验:
$ wget https://labfile.oss.aliyuncs.com/courses/599/rent.csv
3. 设计页面
页面大框架可直接从示例中心复制:高德 JavaScript API 示例中心
这里先给出全部的设计代码,新建index.html复制粘贴下面的代码:
讲解一下部分代码:
这一句中你会看到key这个参数,它需要你注册高德的开发者用户,创建应用才能得到,由于 JS API 不像它家的 Web API 一样有流量限制,所以这个key大可随意使用。