百度地图街景图片爬取 |
您所在的位置:网站首页 › 怎样下载街景地图 › 百度地图街景图片爬取 |
1 需求
抓取整个杭州市的百度/腾讯街景地图及其时光机功能(实时图片和历史图片),进行图像分析。 2 分析百度地图街景模式下,点击向前可发现,街景图片是异步加载的,我们可以打开百度地图的街景模式,f12打开开发者模式,清空所有响应,并点击向前,可以看到产生了很多的图片请求 ![]() 本文以杭州市余杭区文一西路海创园附近处(由西向东)的街景为例仔细分析这些请求的作用: 首先,第一条请求: https://mapsv0.bdimg.com/?qt=qsdata&x=13361258.73664768&y=3518572.1440338427&time=201709&mode=day&px=1336124156&py=351856780&pz=14.89&roadid=eeaa41-bd79-2cf9-3491-2ca35d&type=street&action=0&pc=1&auth=8Nv8G8DBLbO2F1vLvHNAgXOTz4UFPbxHuxHLxBLVHTRt1qo6DF%3D%3DCcvY1SGpuztAFwWv1GgvPUDZYOYIZuVt1cv3uHxtOmm0mEb1PWv3GuxNVt%3DErpTgZp1GHJMP6V8%40aDcEWe1GD8zv7u%40ZPuVteuEthjzgjyBKOBEEUWWOxtx77INHu%3D%3D8x35&udt=20190619&fn=jsonp.p30899897此请求也可简化为(为简便,以下请求均不带auth参数,不影响结果获取): https://mapsv0.bdimg.com/?qt=qsdata&x=13361258.73664768&y=3518572.1440338427&time=201709&mode=day 作用:根据地图上点击的位置,生成百度地图坐标x和y值,再得到服务器的json响应,(如下id即为该位置的百度街景ID,也就是后续要用到的panoID) 作用:该请求包含了panoId参数,返回该位置的街景相关信息(附近panoID,以及该位置的历史图片,拍摄时期等等),下文会详细分析。json响应如下图所示: 作用: 获取该位置附近的公司或学校。json响应如下图所示: 作用: 该请求返回该位置街景的全景图片。如下所示: 作用:该请求返回一个当前视角的小尺寸图片,如图所示: 第六条请求(这是一组大图请求): https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=1_4&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=2_4&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=1_5&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=2_5&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=1_6&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=2_6&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=1_7&z=4 https://mapsv0.bdimg.com/?qt=pdata&sid=09025200121709031616142855K&pos=2_7&z=4
因此我们要得到一座城市、一条街道的街景图片,首先要获取该城市、该街道所有位置的街景ID,然后通过模拟上述图片请求即可,但是如何获取杭州市所有街道的街景ID呢? 网上查了些资料,有人提出的想法是: 1、暴力循环panoID,错误就忽略,正确就返回结果。2、在一条道路寻找一个种子panoID,然后爬取整条道路的所有图片。3、根据百度地图的坐标,设置一个区域,遍历整个区域的所有坐标,正确就返回panoID,错误就不处理。粗略一看感觉很有道理,但仔细一分析就知扯淡! 首先,第一条,暴利循环相当低效,由于百度没有提供整条街道的经纬度接口,也没有提供获得整条街道的所有panoID值的接口(至少我没找到),所以如果根据网友的意思,在给定起始panoID情况下循环试错获取下一个panoID需要发送上万次、数十万次请求,很可能没获取到下一个ID就已经被百度封IP了,第三条,我确实想设置一个区域,但如何遍历该区域所有坐标呢?如何保证街景图片是同一条街道且连续的呢?有大牛想到解决办法的话烦请告知!再来看第二条,似乎可取,重点是如何获取下一个panoID。答案还是在上述"请求二"中。 2.2 请求2详细分析 我们可以看到,Roads[0].Panos标签下,包含有多个panoID,我们可以在街景模式下点击向前10米,浏览器又加载了下个panoID(09025200121709031616155125K)的图片,这里有一个规律,向前20米左右会加载当前panoID的下下个panoID图片,以此类推。 在这里可以根据不同的业务需求采用不同的数据库,关系型或非关系型均可。某种程度上非关系型列式存储可能更好,因为当我们爬取一个城市所有街道的街景时,有的位置有历史数据,有的则没有,因此大规模数据集下可利用列式存储的弹性伸缩实现数据的高效存取。但考虑到后续图像分析时,可能需要建立空间连续(离散)位置的图像模型,这又更适合采用关系型数据库来存取。以mysql与Hbase为例,再回顾一下典型的关系型数据库和非关系型数据库之间的区别: 2.3.1 HBase与MySQL的区别 属性HBaseMySQL存储按列存储,可灵活增加列,列为空时不占存储空间按行存储伸缩扩展性支持需要第三方中间层支持高并发读写支持不支持条件查询只支持按rowkey查询支持数据类型字符串类型多种类型数据操作只有查询、插入、删除、清空等还包括各种连接操作等数据更新实际是插入新的数据,多版本替换修改 2.3.2 二进制流的存储下载几张图片看下大小,然后决定选用何种字段类型,经比较分析,得如下要点: 图片转为二进制字节流表中图片字段设为blob型MySQL 存储blob型数据可参阅此处 3 代码对应上述业务逻辑,编写不同步骤的代码 3.1 建表及读表记录建表,并将起始panoID存入数据库。建表语句如下: CREATE TABLE `test`.`baidu_pano` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pano_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '街景ID', `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '街道名称', `lati` double(32, 0) NULL DEFAULT NULL COMMENT '纬度', `lonti` double(32, 0) NULL DEFAULT NULL COMMENT '经度', `direction` bit(1) NULL DEFAULT NULL COMMENT '0:由西向东;1:由东向西', PRIMARY KEY USING BTREE (`id`) ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'InnoDB free: 30720 kB' ROW_FORMAT = Compact; 插入panoID如图所示: 我们需编写一个从MySQL读取记录并封装结果集的工具类MySQLHelper ,源码如下: public class MySQLHelper { private static final Logger logger = Logger.getLogger(MySQLHelper.class); private static QueryRunner runner; private static ResultSetHandler h = new ResultSetHandler() { @Override public HashMap handle(ResultSet rs) throws SQLException { if (!rs.next()) { return null; } ResultSetMetaData meta = rs.getMetaData(); int cols = meta.getColumnCount(); HashMap result = new HashMap(16); for (int i = 0; i |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |