Python爬取链家的数据并绘制热力图
2017-08-16 18:56
1336 查看
最近开始入坑Python爬虫,专业是地理信息系统,对地理位置相关的信息比较感兴趣,所以就试着爬南京链家的二手房数据,并利用百度API绘制出热力图。Python的版本是Python3.6,然后用到了requests库和BeautifulSoup库还有csv库,IDE用的是PyCharm
,二手房的信息全部保存在li class=’clear’里面,等会用bs库解析网页的时候会用到。
OK,运行代码,就可以看到在程序根目录下出现了da.csv文件,打开可以看到数据已经全部爬好了,查看数据发现经纬度字段会有空值,要在excel中将这些空值删除掉。
所以我们要将我们存储在csv中的数据输出成这样的格式,代码如下(将二手房的关注度作为count的值):
这样在编译器中会输出格式化好的经纬度信息,如下图所示:
接着新建一个html文件,将百度api中的示例代码拷贝进去,将var points中的点值换成刚才输出的值。最后,因为百度由于百度地图JavaScript API热力图默认的是以天安门为中心的北京区域地图,而我们的数据是南京的,所以这里还需要对热力图中“设置中心点坐标和地图级别”的部分进行修改。修改BMap.Point中的值为南京市中心的值,修改级别为12.
最后将html代码如下(因为点的数量实在太多,在这里我就只放三个点进去):
最后,打开html文件,在浏览器中可以看到,热力图的效果如下,看起来还不错。
不过,因为在上面用百度API根据地名查询经纬度的部分,查询得到的经纬度有些并不是南京的,这个问题暂时还没想到解决办法。
一、安装requests库和BeautifulSoup库
windows命令行下,输入pip install requests回车安装完成后,继续输入pip install BeautifulSoup回车二、观察链家二手房网页链家规律以及html规律
南京链家二手房网页为https://nj.lianjia.com/ershoufang/pg1/,其中pg后面的数字表示第几页。所以访问时设置一个列表循环访问即可。再来看看链家网站的html规律,谷歌浏览器开发者模式查看元素,可以看到,二手房的信息全部保存在li class=’clear’里面,等会用bs库解析网页的时候会用到。
三、申请百度开发者密匙,用于后面根据二手房小区的名字查询二手房的经纬度信息
在百度开发者平台上http://lbsyun.baidu.com/,注册,然后申请密匙,应用名称可以随便填,应用类型选择浏览器端即可。百度地图根据名称查询地点的经纬度的教程可以参考 这篇博客http://blog.csdn.net/qq_23926575/article/details/72569995四、爬网页,并将结果存储在csv文件中
准备工作全部完成,开始爬网页,并将结果存储在程序根目录下da.csv中,话不多说,直接上源码from bs4 import BeautifulSoup import requests import csv import re def getlocation(name):#调用百度API查询位置 bdurl='http://api.map.baidu.com/geocoder/v2/?address=' output='json' ak='你的密匙'#输入你刚才申请的密匙 callback='showLocation' uri=bdurl+name+'&output=t'+output+'&ak='+ak+'&callback='+callback res=requests.get(uri) s=BeautifulSoup(res.text) lng=s.find('lng') lat=s.find('lat') if lng: return lng.get_text()+','+lat.get_text() url='https://nj.lianjia.com/ershoufang/pg' heade={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}#请求头,模拟浏览器登陆 page=list(range(0,101,1)) p=[] hi =[] fi=[] for i in page:#循环访问链家的网页 response=requests.get(url+str(i)) soup=BeautifulSoup(response.text) #提取价格 prices=soup.find_all('div',class_='priceInfo') for price in prices: p.append(price.span.string) #提取房源信息 hs=soup.find_all('div',class_='houseInfo') for h in hs: hi.append(h.get_text()) #提取关注度 followInfo=soup.find_all('div',class_='followInfo') for f in followInfo: fi.append(f.get_text()) print(i) #houses=[]#定义列表用于存放房子的信息 n=0 num=len(p) file=open('da.csv', 'w', newline='') headers = ['name', 'loc', 'style', 'size', 'price', 'foc'] writers = csv.DictWriter(file, headers) writers.writeheader() while n<num:#循环将信息存放进列表 h0=hi .split('|') name=h0[0] loc=getlocation(name) style = re.findall(r'\s\d.\d.\s', hi )#用到了正则表达式提取户型 if style: style=style[0] size=re.findall(r'\s\d+\.?\d+',hi )#用到了正则表达式提取房子面积 if size: size=size[0] price=p foc=re.findall(r'^\d+',fi )[0]##用到了正则表达式提取房子的关注度 house = { 'name': '', 'loc': '', 'style': '', 'size': '', 'price': '', 'foc': '' } #将房子的信息放进一个dict中 house['name']=name house['loc']=loc house['style']=style house['size']=size house['price']=price house['foc']=foc writers.writerow(house)#将dict写入到csv文件中 n+=1 print(n) file.close()
OK,运行代码,就可以看到在程序根目录下出现了da.csv文件,打开可以看到数据已经全部爬好了,查看数据发现经纬度字段会有空值,要在excel中将这些空值删除掉。
五、将数据处理成百度地图热力图API需要的格式
百度地图制作热力图的官方文档在http://developer.baidu.com/map/jsdemo.htm#c1_15%E3%80%82中,可以发现,热力图点的数据部分为var points =[ {"lng":经度,"lat":纬度,"count":数值}, {"lng":经度,"lat":纬度,"count":数值}, ... ]
所以我们要将我们存储在csv中的数据输出成这样的格式,代码如下(将二手房的关注度作为count的值):
import csv reader=csv.reader(open('da.csv')) for row in reader: loc=row[1] sloc=loc.split(',') lng='' lat='' if len(sloc)==2:#第一行是列名需要做判断 lng=sloc[0] lat=sloc[1] count=row[5] out='{\"lng\":'+lng+',\"lat\":'+lat+',\"count\":'+count+'},' print(out)
这样在编译器中会输出格式化好的经纬度信息,如下图所示:
接着新建一个html文件,将百度api中的示例代码拷贝进去,将var points中的点值换成刚才输出的值。最后,因为百度由于百度地图JavaScript API热力图默认的是以天安门为中心的北京区域地图,而我们的数据是南京的,所以这里还需要对热力图中“设置中心点坐标和地图级别”的部分进行修改。修改BMap.Point中的值为南京市中心的值,修改级别为12.
最后将html代码如下(因为点的数量实在太多,在这里我就只放三个点进去):
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=lB1LFGD8N6ydaTCSmVxiPYSly973KBHa"></script> <script type="text/javascript" src="http://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script> <title>热力图功能示例</title> <style type="text/css"> ul,li{list-style: none;margin:0;padding:0;float:left;} html{height:100%} body{height:100%;margin:0px;padding:0px;font-family:"微软雅黑";} #container{height:90%;width:100%;} #r-result{width:100%;} </style> </head> <body> <div id="container"></div> <div id="r-result"> <input type="button" onclick="openHeatmap();" value="显示热力图"/><input type="button" onclick="closeHeatmap();" value="关闭热力图"/> </div> </body> </html> <script type="text/javascript"> var map = new BMap.Map("container"); // 创建地图实例 var point = new BMap.Point(118.800459,32.06715); map.centerAndZoom(point, 12); // 初始化地图,设置中心点坐标和地图级别 map.enableScrollWheelZoom(); // 允许滚轮缩放 var points =[ {"lng":101.538291069,"lat":30.0223723448,"count":41}, {"lng":101.727603422,"lat":36.6316356868,"count":8}, {"lng":99.7141240332,"lat":27.8175439265,"count":44}]; if(!isSupportCanvas()){ alert('热力图目前只支持有canvas支持的浏览器,您所使用的浏览器不能使用热力图功能~') } //详细的参数,可以查看heatmap.js的文档 https://github.com/pa7/heatmap.js/blob/master/README.md //参数说明如下: /* visible 热力图是否显示,默认为true * opacity 热力的透明度,1-100 * radius 势力图的每个点的半径大小 * gradient {JSON} 热力图的渐变区间 . gradient如下所示 * { .2:'rgb(0, 255, 255)', .5:'rgb(0, 110, 255)', .8:'rgb(100, 0, 255)' } 其中 key 表示插值的位置, 0~1. value 为颜色值. */ heatmapOverlay = new BMapLib.HeatmapOverlay({"radius":20}); map.addOverlay(heatmapOverlay); heatmapOverlay.setDataSet({data:points,max:100}); //是否显示热力图 function openHeatmap(){ heatmapOverlay.show(); } function closeHeatmap(){ heatmapOverlay.hide(); } closeHeatmap(); function setGradient(){ /*格式如下所示: { 0:'rgb(102, 255, 0)', .5:'rgb(255, 170, 0)', 1:'rgb(255, 0, 0)' }*/ var gradient = {}; var colors = document.querySelectorAll("input[type='color']"); colors = [].slice.call(colors,0); colors.forEach(function(ele){ gradient[ele.getAttribute("data-key")] = ele.value; }); heatmapOverlay.setOptions({"gradient":gradient}); } //判断浏览区是否支持canvas function isSupportCanvas(){ var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); } </script>
最后,打开html文件,在浏览器中可以看到,热力图的效果如下,看起来还不错。
不过,因为在上面用百度API根据地名查询经纬度的部分,查询得到的经纬度有些并不是南京的,这个问题暂时还没想到解决办法。
相关文章推荐
- python绘制excel数据热力图
- Python绘制时间序列数据的时序图、自相关图和偏自相关图
- 利用Python绘制数据的瀑布图的教程
- Python数据挖掘课程 七.PCA降维操作及subplot子图绘制
- python数据挖掘学习】十五.Matplotlib调用imshow()函数绘制热图
- 【python数据挖掘课程】十五.Matplotlib调用imshow()函数绘制热图
- python爬取链家数据
- Python实现从excel读取数据并绘制成精美图像
- 【数据可视化】Daft:(Python)基于matplotlib绘制精美概率图模型
- python实战二:使用CSV数据绘制带数据标志的折线图(matplotlib)
- Windows下使用python绘制caffe中.prototxt网络结构数据可视化
- python matplotlib模块——绘制三维图形、三维数据散点图
- 【Python那些事儿】为多变量数据绘制散点图
- Python爬虫:获取链家,搜房,大众点评的数据
- Python进阶(三十八)-数据可视化の利用matplotlib 进行折线图,直方图和饼图的绘制
- 准备工作-用python绘制金融数据曲线的进阶实例
- Python数据挖掘笔记 七 .PCA降维操作及subplot子图绘制
- python/folium绘制中国人口数量热力图(HeatMap)
- Python绘制直方图(Histograms)—从文件中读取数据画图update@2017-05-17
- 在Linux下使用Python的matplotlib绘制数据图的教程