我工作的项目里,经?;崤龅娇突Ц龅刂妨斜恚颐且桓鲆桓鲈诘赝忌纤阉鞯那榭?。为此,趁着周末稍有小闲,用Python写一个批量标注的。
程序逻辑:从excel里读取地址列表?→每个地址搜索一遍,百度地图API会返回url→打开url(好像用到了爬虫的基?。?,得到经纬度→在百度开发者平台上的html里,直接批量输入经纬度即可显示。
首先,介绍一下百度地图的开发平台,里面会涉及申请一个开发者账号,然后创建一个程序,以获得ak和sk。我是用sn的方式验证的,代码如下:(百度前几天V2升V3,链接变了,还坑了我一下)
def get_url(address):
? ?# V2: http://api.map.baidu.com/geocoder/v2/?address=搜索地址&output=json&ak=你的ak
? ? # V3: http://api.map.baidu.com/geocoding/v3/?address=百度大厦&output=json&ak=您的ak&callback=showLocation
? ? # V3版本中后缀callback加入链接后,会导致后续jason解析出错,所以不要加
? ? queryStr ='/geocoding/v3/?address=' + address +'&output=json&ak=' + ak
? ? # 对queryStr进行转码,safe内的保留字符不转换
? ? encodedStr = parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
? ? # 在最后直接追加上你自己的sk
? ? rawStr = encodedStr + sk
? ? # 计算sn
? ? sn = (hashlib.md5(parse.quote_plus(rawStr).encode("utf8")).hexdigest())
? ? # 由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
? ? url = parse.quote("http://api.map.baidu.com" + queryStr +"&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
? ? return url
这里ak和sk字符串提前定义好即可。多说一句,有人反馈找不到sk,在百度地图api应用列表里,点击设置进去就有,ak在最上,sk在最下。以上代码是从这篇文章抄的。
得到的url其实可以在浏览器里直接打开,浏览器里就能返回我们想要的经纬度。
用request解析url,之前看过两眼爬虫的技巧,所以还try了一下,不过估计没必要。用Jason得到一个包含经纬度的套了三层的字典。
def url_Open(url):
# 爬取网页通用代码框架,需要用try
? ? try:
? ? ? ? testResponse = requests.get(url)
? ? ? ? # 只要返回码不是200(200为正常),就会抛出异常
? ? ? ? testResponse.raise_for_status()
????????# 剔除可能的解码异常
? ? ? ? testResponse.encoding = testResponse.apparent_encoding
? ? ? ? return testResponse.json()
except:
print("获取失败")
return "产生异常"
上一步做完,剩下的就是把经纬度信息封装到一个字典里即可,然后就卡在怎么在地图显示了,这个问题还是研究了一会儿的,直到搜到这篇文章。文章里给出的链接貌似是百度地图开发者一个测试????连接已经更新了,原文的链接失效了,新的链接:地图API示例。这里要注意的是,“源代码编辑器里的”ak是不用填的,反正我不填可以在这个界面直接用。填了反而会报错说没权限。如果导出html直接打开的话,不管填不填ak,都会说没权限。
其他的设置代码备注已经说得很清楚了。
以下代码贴到“源代码编辑器”,然后点击运行即可。
<!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:"微软雅黑";}
</style> <script type="text/javascript"
//ak填自己申请的ak
src="http://api.map.baidu.com/api?v=2.0& ak=您的密钥">
</script> <title>百度地图api展示</title> </head> <body> <div id="allmap"></div> </body> </html> <script type="text/javascript">
//新建三个地图上点
var points = [
//这里填你之前封装的包含经纬度的字典即可。
//示例:{'lat': 38.946090694889435, 'lng': 117.43834526985445, 'quyu': '第1个地址'}, {'lat': 36.87390250014566, 'lng': 115.46647728073067, 'quyu': '第2个地址'}, {'lat': 34.90387458594099, 'lng': 117.4259256589923, 'quyu': '第3个地址'}
];
//创建标注点并添加到地图中
function addMarker(points) {
? ? //循环建立标注点
? ? for(var i=0, pointsLen = points.length; i<pointsLen; i++) {
? ? ? ? var point = new BMap.Point(points[i].lng, points[i].lat); //将标注点转化成地图上的点
? ? ? ? var marker = new BMap.Marker(point); //将点转化成标注点
? ? ? ? map.addOverlay(marker);? //将标注点添加到地图上
? ? ? ? //添加监听事件
? ? ? ? (function() {
? ? ? ? ? ? var thePoint = points[i];
? ? ? ? ? ? marker.addEventListener("click",
? ? ? ? ? ? ? ? function() {
? ? ? ? ? ? ? ? showInfo(this,thePoint);
? ? ? ? ? ? });
? ? ? ? })();?
? ? }
}
function showInfo(thisMarker,point) {
? ? //获取点的信息
? ? var sContent =
? ? '<ul style="margin:0 0 5px 0;padding:0.2em 0">'?
? ? +'<li style="line-height: 26px;font-size: 15px;">'?
? ? +'<span style="width: 50px;display: inline-block;">id:</span>' + point.quyu + '</li>'?
? ? +'<li style="line-height: 26px;font-size: 15px;">'?
? ? +'<span style="width: 50px;display: inline-block;">纬度:</span>' +
? ? ? ? point.lat +
? ? ? ? '<span style="width: 50px;display: inline-block;"> 经度:</span>' + point.lng +'</li>'?
? ? +'</ul>';
? ? var infoWindow = new BMap.InfoWindow(sContent); //创建信息窗口对象
? ? thisMarker.openInfoWindow(infoWindow); //图片加载完后重绘infoWindow
}
//创建地图
var map = new BMap.Map("allmap");? ?
map.centerAndZoom(new BMap.Point(118.164, 24.530), 30);? // 设置中心点
map.centerAndZoom( "厦门");
map.setCurrentCity("厦门");? ? ? ? ? //设置上海
map.addControl(new BMap.MapTypeControl());?
map.enableScrollWheelZoom(true);? ?
addMarker(points);
</script>
然后就在右侧的地图上看到批量标记的点了。