我们研究生的课程内容,做下笔记记录一下。

使用的python环境是python3.7

用的图大部分都是老师ppt里的图,懒得自己截了……

申请百度开发者密匙

(1)注册百度用户,注册过的话,直接登录就可以。登录地址为百度地图开放平台

(2)登录后,在控制台点击【创建应用】。

(3)填写表单,创建应用

(4)这样就得到了API Key了

百度地图搜索API语法

poi查询的基本url为http://api.map.baidu.com/place/v2/search?

按矩形框坐标范围检索

有如下参数

参数名 参数含义 类型 是否必须
query 检索关键字,周边检索和矩形区域检索
支持多关键字(以$隔开)并集检索,最多支持10个。
string(45) Y
bounds 设置查询的坐标范围
矩形框的左下角经纬度和右上角经纬度。
string(50) Y
output 输出格式为json或xml string(50) Y
scope 检索结果的详细程度
取值为1或空,返回基本信息;取值2,返回详细信息
string(50) N
page_size 页面显示POI数量,默认值为10条,最大值为20 int N
page_num 分页页码,从0开始 int N
coord_type 坐标类型
1:WGS84即GPS经纬度坐标
2:国家测绘局GCJ-02坐标
3:bd09,即百度经纬度坐标
4:bd09mc即百度米坐标
int N
ret_coordtype 返回国测局经纬度坐标 string(50) N
ak 开发者访问密钥(刚刚申请的API KEY) string(50) Y

关于上面这个bounds的值,可以使用百度地图自己提供的坐标拾取器获得。也可以通过别人写的一个网页获得具体的行政区矩形框。

别人写的网页的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" />
<style type="text/css">
body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
#panel{
position:absolute;
left:5px;
top:5px;
}
#result{
background: #fff;
padding:5px;
}
</style>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=1XjLLEhZhQNUzd93EjU5nOGQ"></script>
<title>添加行政区划</title>
</head>
<body>
<div id="allmap"></div>
<div id="panel">
<div>
<input type="text" id="keyword" value="昆明市"/>
<input type="button" value="查看范围" id="commitBtn"/>
边界经纬度坐标
<textarea id="pathStr"></textarea>
边界墨卡托坐标
<textarea id="pathMc"></textarea>
</div>
<div id="result">
</div>
</div>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("allmap");
map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);
map.enableScrollWheelZoom();
var mercatorProjection = map.getMapType().getProjection();
$("#commitBtn").bind('click', function(){
getBoundary($("#keyword").val());
});
function getBoundary(city){
var bdary = new BMap.Boundary();
bdary.get(city, function(rs){ //获取行政区域
map.clearOverlays(); //清除地图覆盖物
var count = rs.boundaries.length; //行政区域的点有多少个
if (count === 0) {
alert('未能获取当前输入行政区域');
return ;
}
var pointArray = [];
for (var i = 0; i < count; i++) {
var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物
map.addOverlay(ply); //添加覆盖物
pointArray = pointArray.concat(ply.getPath());
}
var pathStr = "";
var pathMc = "";
for (var i = 0; i < pointArray.length; i++) { var mc = mercatorProjection.lngLatToPoint(pointArray[i]);
pathStr += pointArray[i].lng + "," + pointArray[i].lat + ";";
pathMc += mc.x + "," + mc.y + ";";
}
$('#pathStr').html(pathStr);
$('#pathMc').html(pathMc);
var ply = new BMap.Polygon(pointArray , {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物
var bounds = ply.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var neMc = mercatorProjection.lngLatToPoint(ne);
var swMc = mercatorProjection.lngLatToPoint(sw);
var str = "经纬度:左下角,右上角:" + sw.lng + "," + sw.lat + ";" + ne.lng + "," + ne.lat
+ "<br/>墨卡托坐标:左下角,右上角:" + swMc.x + "," + swMc.y + ";" + neMc.x + "," + neMc.y;
$('#result').html(str);
console.log(bounds);
map.setViewport(pointArray); //调整视野
});
}
//getBoundary('北京');
</script>

打开后,类似这样

按城市检索

刚刚说的是按bound检索。也可以使用region参数按城市检索,比如说

http://api.map.baidu.com/place/v2/search?query=公园&region=武昌区&output=json&ak=xxxxxxxxx&page_size=20&page_num=0

周边检索

使用location参数(设置中心点坐标)和radius参数(设置半径)进行周边检索。比如说

http://api.map.baidu.com/place/v2/search?query=酒店&location=30.531642,114.366409&radius=300&output=json&ak=xxxxxxxxxx&page_size=20&page_num=0

返回内容

返回的内容,status为状态(0为成功返回,其他为异常),message为提示信息,total为返回的poi数量,results为当前页的poi信息。

{
"status":0,
"message":"ok",
"total":57,
"results":[]
}

一般scope为1的poi信息如下

 {
"name":"四美塘",
"location":{
"lat":30.603315,
"lng":114.344284
},
"address":"武汉市武昌区和平大道589号(长江二桥下)",
"province":"湖北省",
"city":"武汉市",
"area":"武昌区",
"street_id":"15a93810075519bd15c8f6b4",
"detail":1,
"uid":"f21f49135aad2a3ce856fad9"
}

一般scope为2的poi信息如下

{
"name":"四美塘",
"location":{
"lat":30.603315,
"lng":114.344284
},
"address":"武汉市武昌区和平大道589号(长江二桥下)",
"province":"湖北省",
"city":"武汉市",
"area":"武昌区",
"street_id":"15a93810075519bd15c8f6b4",
"detail":1,
"uid":"f21f49135aad2a3ce856fad9"
"detail_info":{
"tag":"旅游景点;公园",
"navi_location":{
"lng":114.34584347395,
"lat":30.604976470638
},
"type":"scope",
"detail_url":"http://api.map.baidu.com/place/detail?uid=f21f49135aad2a3ce856fad9&output=html&source=placeapi_v2",
"overall_rating":"4.3",
"comment_num":"14",
"children":[ ]
}
}

百度地图POI搜索爬虫设计

由于百度地图限制每次返回的poi最多只有400个,所以我们要把矩形区域进行分割以获得更多的数据。

具体实现的代码如下

def splitArea(bound):
# 分割矩形区域的函数
boundList=[]
row_num = 2 # 按照 2 X 2 进行分割
bound=list(map(float,bound.split(',')))
step_lat = (bound[2] - bound[0]) / row_num
step_lon = (bound[3] - bound[1]) / row_num
for i in range(0,row_num):
for j in range(0,row_num):
boundTemp = []
boundTemp.append(bound[0]+step_lat*i)
boundTemp.append(bound[1]+step_lon*j)
boundTemp.append(bound[0]+step_lat*(i+1))
boundTemp.append(bound[1]+step_lon*(j+1))
boundTemp=",".join(["%s" %x for x in boundTemp])
boundList.append(boundTemp)
return boundList

课后作业完成

题目如下:

寻找武汉市中学(或小学)周围500米(或其他)内的网吧

要求:提交代码py文件及运行结果文件(txt),txt文件格式如下:

1,XXX小学

1-1,XXX网吧

1-2, XXX网吧

2,XXX小学

2-1,XXX网吧

2-2, XXX网吧

………..

写的python3代码为

# coding:utf-8
# version:python3.7
# author:Ivy ############# 程序功能 ####################
# 本程序用来获取百度地图某城市某种poi周围一定范围内的另一种类型的poi数据
# 如示例是获取武汉市中学周围500米内的网吧
# 生成的info.txt格式如下
# 1, xxx中学
# 1-1, xxx网吧
# 1-2, xxx网吧
# 2, xxx中学
# 2-1, xxx网吧
############################################ import requests,json
import time,sys ############### 自主设置区 ###############
ak = 'xxxxxxxxx' #API key
keyword="中学"
keyword2="网吧"
radius=500
city="武汉市"
baseBound = '29.972898,113.707695,31.367052,115.085775' #武汉市矩形框的左下角经纬度和右上角经纬度
############################################ # 构造header
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
'Accept-Encoding':'gzip, deflate',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'Host': 'api.map.baidu.com',
'Upgrade-Insecure-Requests': '1',
'Connection': 'keep-alive',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'DNT': '1'
} baseUrl="http://api.map.baidu.com/place/v2/search?query={}&bounds={}&page_size=20&page_num={}&output=json&ak={}"
searchBaseUrl="http://api.map.baidu.com/place/v2/search?query={}&location={}&radius={}&output=json&ak={}&page_size=20&page_num={}" def req(url):
# 访问url获取返回的数据读取为json
errorNum=0
while True:
try:
res = requests.get(url,headers=headers)
res.encoding='utf-8'
jd = json.loads(res.text)
return jd
except Exception as e:
errorNum+=1
print("出错了!")
print(e)
if errorNum==5:
sys.exit(1)
time.sleep(1) def splitArea(bound):
# 分割矩形区域的函数
boundList=[]
row_num = 2 # 按照 2 X 2 进行分割
bound=list(map(float,bound.split(',')))
step_lat = (bound[2] - bound[0]) / row_num
step_lon = (bound[3] - bound[1]) / row_num
for i in range(0,row_num):
for j in range(0,row_num):
boundTemp = []
boundTemp.append(bound[0]+step_lat*i)
boundTemp.append(bound[1]+step_lon*j)
boundTemp.append(bound[0]+step_lat*(i+1))
boundTemp.append(bound[1]+step_lon*(j+1))
boundTemp=",".join(["%s" %x for x in boundTemp])
# 是否要继续分割
if check(boundTemp):
boundList.append(boundTemp)
else:
boundList+=splitArea(boundTemp)
return boundList def check(bound):
# 检查一下当前矩形框是否需要再次分割
checkUrl=baseUrl.format(keyword,bound,0,ak)
checkJd=req(checkUrl)
if checkJd["total"]<400:
return True
return False def getPois(bound):
# 获取一定范围内所有的想要的poi的信息
poiListTemp=[]
pageNum=0
while True:
getUrl=baseUrl.format(keyword,bound,pageNum,ak)
getJd=req(getUrl)
if getJd['results']==[]: # 如果这一页没数据了就是结束啦,退出循环
break
for result in getJd['results']:
if result["city"] != city: # 在矩形框中,但是不是想要的城市的,就不要记录啦
continue
poiListTemp.append(result)
pageNum+=1
print("当前区域{}的poi已爬完,共有{}个".format(bound,len(poiListTemp)))
return poiListTemp def searchPois(poiInfo):
# 获取某个poi周边的其他poi信息
poiListTemp=[]
pageNum=0
while True:
searchUrl=searchBaseUrl.format(keyword2,str(poiInfo['location']['lat'])+','+str(poiInfo['location']['lng']),radius,ak,pageNum)
searchJd=req(searchUrl)
if searchJd['results']==[]:
break
for result in searchJd['results']:
poiListTemp.append(result["name"])
print(result["name"]," 已添加")
pageNum+=1
print(poiInfo["name"],"周边poi已爬完")
return [poiInfo["name"],poiListTemp] if __name__ == '__main__':
# 分割想要的区域
boundList=splitArea(baseBound)
print(boundList) # 获取范围内所有的poi信息
poiList=[]
for bound in boundList:
poiList+=getPois(bound)
print('已获得所有poi信息') # 对于获取到的每个poi进行周边检索
infoList=[]
for poi in poiList:
infoList.append(searchPois(poi))
print('已获得所有周边poi信息') # 把获取到的信息都写入txt
with open('info.txt','w') as f:
for i in range(len(infoList)):
f.write(str(i+1)+', '+infoList[i][0]+'\n')
for j in range(len(infoList[i][1])):
f.write(str(i+1)+'-'+str(j+1)+', '+infoList[i][1][j]+'\n')
print("所获得的信息已全部写入txt啦!")

【参考】

[1]我们老师的PPT(不便公开)

百度地图POI爬取的更多相关文章

  1. 百度地图POI数据爬取,突破百度地图API爬取数目“400条“的限制11。

    1.POI爬取方法说明 1.1AK申请 登录百度账号,在百度地图开发者平台的API控制台申请一个服务端的ak,主要用到的是Place API.检校方式可设置成IP白名单,IP直接设置成了0.0.0.0 ...

  2. 高德地图POI爬取_Python

    高德地图POI 官方文档:https://lbs.amap.com/api/webservice/guide/api/search#introduce 官网控制台:https://lbs.amap.c ...

  3. 教你如何拔取百度地图POI兴趣点

    教你如何拔取百度地图POI兴趣点   通过聚合数据提供的接口,获取百度地图的POI兴趣点,并存储至数据库中. 实现: 1.聚合数据百度POI接口说明 调用聚合数据,首先得注册聚合.聚合数据提供的百度地 ...

  4. 基于 Golang 完整获取百度地图POI数据的方案

    百度地图为web开发者提供了基于HTTP/HTTPS协议的丰富接口,其中包括地点检索服务,web开发者通过此接口可以检索区域内的POI数据.百度地图处于数据保护对接口做了限制,每次访问服务,最多只能检 ...

  5. 获取百度地图POI数据三(模拟关键词搜索)

    上一篇博文中讲到如何获取用于搜索的关键词,并且已经准备好了一百五十万的关键词   这其中有门牌号码,餐馆酒店名称,公司名称,道路名称等.有了这些数据,我们就可以通过代码,模拟我们在百度地图的搜索框中搜 ...

  6. 获取百度地图POI数据二(准备搜索关键词)

    上篇讲到  想要获取尽可能多的POI数据 需要准备尽可能多的搜索关键字   那么这些关键字如何得来呢?   本人使用的方法是通过一些网站来获取这些关键词   http://poi.mapbar.com ...

  7. 第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息 crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多 ...

  8. 十三 web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多网站,当你浏览器访问时看到的信息,在html源文件里却找不到,由得信息还是滚动条滚动到对应的位置后才显示信息, ...

  9. iOS地图集成示例:百度地图POI检索

    一.集成百度地图(傻瓜教程,以网站说明文档为准,此处罗列几项主要步骤) 1.登录  http://lbsyun.baidu.com  百度地图开发者平台,获取SDK和集成文档. 2.百度地图可以提供的 ...

随机推荐

  1. ​TDD明白了,ATDD测试到底是什么?

    随着敏捷开发的蓬勃发展.遍地开花,TDD(Test Drive Development测试驱动开发)的概念已经深入软件研发从业者的心中. TDD讲究的是:“测试在先.编码在后”.有别于以往的“先编码. ...

  2. Codeforces Round #581 (Div. 2) C. Anna, Svyatoslav and Maps (Floyd 算法,最短路)

    C. Anna, Svyatoslav and Maps time limit per test2 seconds memory limit per test256 megabytes inputst ...

  3. 读取web.xml中设置的参数

    以获取Filer元素里设置的参数为例 先在web.xml文件中配置如下 <?xml version="1.0" encoding="UTF-8"?> ...

  4. JAVA基础编程之打印99乘法表

    需求:打印9*9乘法表 技术考核: 1.for嵌套循环 代码: // 打印99乘法表 public static void print99Table() { System.out.println(&q ...

  5. win7系统安装虚拟网卡进行与Linux虚拟机的通信

    有网络情况下,安装Linux时选择网桥即可实现Window与Linux直接通信. 无网络情况下,最简单的方法是在window系统中安装虚拟网卡,以进行与Linux的通信,步骤如下: (1)右击“我的计 ...

  6. Entity Framework Core 迁移命令

    Add-Migration init Update-Database init 修改model后,执行迁移的命令 更新数据库 每次更新都要{update}修改 Add-Migration {updat ...

  7. Python前端HTML

    一.web标准介绍 web标准: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web标准规范的分类:结构标准.表现标准.行为标准. 结构:html.表示: ...

  8. 51nod 1402 最大值(贪心)

    原题链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1402 思路:借鉴了这篇博文http://blog.csdn.n ...

  9. 使用git将代码上传到GitHub

    使用git将代码上传到GitHub   结束了前一段的时间的杂七杂八的生活,最近又快开始动一动已经吃了好长时间土的GitHub,以前的git指令基本上忘个差不多,现在记录一下,利用git将代码上传. ...

  10. oracle(转)

    Oracle数据库基本操作 1.概述 Oracle数据库客户端一般需要安装在服务器上,可以在服务器端操作,一般我们可以用sql developer工具远程连接到数据库,先行建立数据库,然后对表进行增删 ...