最近对街景地图非常感兴趣,一直想着从什么地方抓取到足够多的图片,这样我就可以用来做很多的分析。(一开始我想的是,要是街边的摄像头的录像都可以为我所用就好啦)
我看到百度地图上提供了街景图片的功能,城市里几乎都有街景地图,大一点的城市同一个地方甚至提供了好多时间可以供你选择。
这么好的数据,怎么能不爬下来呢。
一开始我想到的是用selenium打开浏览器查看地图,用截图的方法来保存图片,但是发现有两个弊端。
- 截图有水印,不便于之后对百度街景地图进行分析
- 截图速度很慢
后来想了想,这些街景图片肯定是异步加载的啊,于是打开f12开发者模式进行抓包,清除所有网络请求,并在地图上做向前的动作。
在右边找到一堆的图片,百度使用这些图片拼接成我们看到的街景图片模式。
经过分析,很快就定位到了我们想要的请求。
这个链接才是我们想要的接口:
url = "https://mapsv0.bdimg.com/?qt=pr3d&fovy=35&quality=80&panoid=09000200011704011540405782F&heading=13.579&pitch=0&width=1024&height=400"
使用Postman向接口发送请求,很快就拿到了一张图片。
实际上,panoid=09000200011704011540405782F是这个图片的唯一标识,其他的几个参数可以调节俯仰角度,焦距,图片尺寸,分辨率等参数,假如将长宽设置得足够宽,后期完全可以对图片进行堆叠处理,去除掉百度的logo。
观察网络请求发现了另外一个接口。
https://mapsv0.bdimg.com/?qt=sdata&sid=09000200011704011540405782F&pc=1&auth=exDCHCC1y0UYeQf7SOvWyza3KT4JPvwNuxHBLVLHVRHtzljPyBYYx1GgvPUDZYOYIZuVt1cv3uVtGccZcuVtcvY1SGpuHt69AN3zFyWykiO=UixAXXXXXXXXXwWvPYuxt8zv7u@ZPuVteuVtegvcguxHBLVLENREthl44yYxrZZWuB&udt=20180830&fn=jsonp.p46758398
我去除了无意义的参数,得到了更为精简的接口地址
https://mapsv0.bdimg.com/?qt=sdata&sid=09000300011605241736364905Q&udt=20180830
向这个接口发送请求,得到了以下的结果。
可以看到向接口传的ID就是第一个ID,接口返回了几个PID,由此可以推断每一个PID都是一个地点的道路图片标识,把PID传入上方链接则会返回附近点的图片标识,如此遍历循环,就能获取一条道路的所有图片。
但是这个PID是怎么来的呢?
打开百度地图并切换到全景将鼠标放在地图上,可以看到随着鼠标的移动会不断的产生response.
通过分析网络请求,可以发现这个接口
https://mapsv0.bdimg.com/?qt=qsdata&x=12726165.823753473&y=3539359.7796100094
在postman中调一下这个接口,得到以下结果。
其中包含了道路名称,我们想要的sid,还有拍摄这个照片的坐标值,当然这个坐标不是GPS而是百度地图的坐标格式。
由于街景地图只有道路有,所以地图的很多地方都是没有结果的。只有在道路附近才会返回正确的sid,而且距离太近返回的sid也是一致的。
所以最后大概有三种方法可以满足我的条件:
- 暴力的循环pid,错误就忽略正确就返回结果
- 在一条道路寻找一个种子pid,然后爬取整条道路的所有图片
- 根据百度地图的坐标,设置一个区域,遍历整个区域的所有坐标,正确就返回pid,错误就不处理。
当然也可以将这三种方式结合起来进行爬取。
发表回复