2013年12月30日 星期一 17:12:33 晴

by Again 2013-12-30 17.12.38

  • 先说名几句题外话:
  • 第一,由于需要我也是半路出家,所以多专业就谈不上了。说白了js和用到的c#我几乎也是个小白,
    我还是比较熟悉c++。还好有多少编程经验,所以不至于手足无措。以下的文章,并不会细致入微地介绍所有内容,
    主要是走过的路给遇到相同问题的朋友留下点足迹,不至于被坑得太惨。

  • 第二,主要目的是比较明确做出离线地图的功能,所以要求快、够用就好为原则。
    百度地图和谷歌地图,其实在版权上都是不允许下载他们的东西的,但是老哥在祖国没有地位,小黑一把,
    百度的话权当“我只看看,不买,请不要管我,谢谢啊”。
    如果对我的帖子涉及任何版权相关问题,请联系我,马上删帖。
    程序主要部分以针对谷歌地图拉取为主。百度地图其实原理也通用

  • 第三,不发文件,源码核心部分已经在下文有描述。市面上大部分地图捉取工具都要收费,目前还搞不清楚是不是有什么利益纠葛,
    所以我就不发这个自己做的工具了,喜欢自己动手丰衣足食的朋友们,相信看完必定离做出来也不远了,希望能帮到你们。
    代码部分用的都是c#自带的类库,除了下载js api以外,你还需要一个不断网的电脑(这个,作为一个穷屌丝,我不能提供)

  • 第四,如有什么更好的建议,恕我愚钝,请一一点明,谢谢。

...
百度地图API 由可让您在接受使用条款约束的情况下,在您的网站上显示百度地图图片;进行地点搜索、路线查询、交通流量显示;发送短信分享地理位置信息等操作。您只可使用在百度地图API文档中所列明开放的API功能来对API相关服务数据的结果进行展示,不得直接存取、使用内部数 据、图片、程序、模块或是任何其他百度地图的服务或功能。在接受使用条款约束的情况下,您可以在向最终用户提供其他信息的同时,使用 API 获得API相关服务数据。百度地图API面向公众服务类网站是免费的,但前提是您的网站所提供给用户的地图服务模块也必须是免费的。如果您使用百度地图且用于商业应用(如GPS运营等),从而直接或间接获得收益,您需要同百度地图另行达成协议或获得百度地图的事先书面许可。...
来源: <http://developer.baidu.com/map/law.htm>
...
2. 使用限制。未经 Google 或特定内容提供商(如果有)的事先书面授权,您不得进行以下任何操作:(a) 对内容或内容的任何部分进行复制、翻译、修改或制作衍生作品;(b) 通过再分发、转许可、出租、发布、销售、转让、租赁、交易、转移或其他方式将产品或内容提供给第三方;(c) 进行反向工程、反编译或通过其他方式试图提取服务或其任何部分的源代码,但适用法律明确允许或要求的情况除外;(d) 通过可让您或其他任何人批量下载任何内容或对其批量提供 Feed(包括但不限于纬度/经度数值坐标、图像和可显示的地图数据)的方式使用产品;(e) 删除、隐藏或通过任何方式改变产品或内容中显示的任何警告或链接;或 (f) 出于下列或相关用途将服务或内容与任何产品、系统或应用结合起来使用,这些用途包括:(i) 实时导航或路线导航(包括但不限于与用户已启用传感器的设备的位置保持同步的精细路线导航);或 (ii) 任何用于自动或自主控制交通工具行为的系统或功能;(g) 使用产品创建地方信息或其他本地商家信息数据库。来源: <http://www.google.com/intl/zh-CN_cn/help/terms_maps.html>...

目录

  • 1.找到响应下载图片链接的地址
  • 2.程序解析地址
  • 3.如何推算出余下需要下载的地址
  • 4.如何下载图片
  • 5.如何命名目录
  • 6.如何读取刚才保存的图片

正文

1.找到响应下载图片链接的地址

首先是下到各家的api,理论上来讲下的是一个js文件。然后找到被调用,
生成下载图片地址的函数,然后改成调用自己的程序,记录这个调用的规则和参数。
当然本办法是直接用浏览器看,譬如火狐,看拉取链接,自己手动记录不同层的起始和终结坐标,解析下载url
就避免了直接改代码,不过最后你要调用图片的时候还是得改,至少延后了,或者你只需要图片呢?呵呵

百度地图
百度家的是乱码加密过的,高不高得定就自求多福吧。
看看浏览器拉取图片的地址,然后搜索"?qt=tile&x="
意外收获,找到瓦片拉取的函数了,先alter一下,看看拉取图片地址正不正常。
正常的话,直接获取对应的x y z变量。或者解析url字串,随你大同小异,我的方法比较笨,获得x y z后组成字符串再传到c#里
我觉得字符串是最好处理的,特别是不同语言之间,毫无压力。

Yb.getTilesUrl = function (a, b) {    //获得瓦片图片var c = a.x;var d = a.y;//X Y Zvar e = "pl";this.map.Ne() && (e = "ph");var resultURL = (Xb[p.abs(c + d) % Xb[w]] + "?qt=tile&x=" + (c + "").replace(/-/gi, "M") + "&y=" + (d + "").replace(/-/gi, "M") + "&z=" + b + "&styles=" + e + (6 == I.O.T ? "&color_dep=32&colors=50" : "") + "&udt=20130712").replace(/-(\d+)/gi, "M$1");//alert(resultURL);window.external.mapLoadCallback(a.x+'|'+a.y+'|'+b);return resultURL;
};

谷歌地图
谷歌地图的话去搞了个gmap包,里面是别人搞好的代码。现在已经不知道在哪里搞回来的了
“GoogleMapAPI3的离线JS版本”

  <!-- 加载离线地图 --><script type="text/javascript" src="mapapi3.8.6.js"></script><!-- 加载在线地图
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
--><script type="text/javascript">//获得瓦片函数
LocalMapType.prototype.getTile = function(coord, zoom, ownerDocument) {var img = ownerDocument.createElement("img");img.style.width = this.tileSize.width + "px";img.style.height = this.tileSize.height + "px";//地图存放路径//谷歌矢量图 maptile/googlemaps/roadmap//谷歌影像图 maptile/googlemaps/roadmap//MapABC地图 maptile/mapabc/var strURL = "maptile/googlemaps/roadmap/";strURL += zoom + "/" + coord.x + "/" + coord.y + ".PNG";//回调函数,用于记录用到的图片范围 by Again 2013-11-13 9.58.48var saveFile = zoom + "|" + coord.x + "|" + coord.y;window.external.mapLoadCallback(saveFile);img.src = strURL;return img;
};</script>

在c#winfrom里面拖了个webbowser,调用一个调用了api的index.html
至于怎么样c#和html之间的js互相调用这里就不详细描述了

2.如何推算出余下需要下载的地址

我的方法是这样的,自己选取一个矩形区域的两个顶角,从某一层(最高层),到另一层(最底层)通过鼠标滚轮,
缩放地图,地图js就会调用你的函数分析下载图片地址。同时,你可以根据对应的层,填充下方数组,
这样每一层的矩形区域,x y最大最小都可以一一得出。

根据谷歌的瓦片算法(全球)、或者百度地图的瓦片算法(中国大陆地区)都是直接两个for循环嵌套即可全部地址计算出来

创建数组,用于存储矩形

int[] Level_map_x_min = new int[20];
int[] Level_map_y_min = new int[20];
int[] Level_map_x_max = new int[20];
int[] Level_map_y_max = new int[20];

3.程序解析地址

//地图回调函数
public void mapLoadCallback(string mapLocation)
{try{string[] strGroup = mapLocation.Split('|');if (strGroup.Count() == 3){int z = System.Int32.Parse(strGroup[0]);//语句1int x = System.Int32.Parse(strGroup[1]);//语句1int y = System.Int32.Parse(strGroup[2]);//语句1//更新X最大最小值Level_map_x_min[z] = x < Level_map_x_min[z] ? x : Level_map_x_min[z];Level_map_x_max[z] = x > Level_map_x_max[z] ? x : Level_map_x_max[z];//更新Y最大最小值Level_map_y_min[z] = y < Level_map_y_min[z] ? y : Level_map_y_min[z];Level_map_y_max[z] = y > Level_map_y_max[z] ? y : Level_map_y_max[z];}}catch (System.Exception ex){MessageBox.Show(ex.ToString()+"\n"+mapLocation);}}

4.如何命名目录

5.如何下载图片

首先通过上面的方法,得到保存了各个层次x y 坐标矩形顶角信息
然后就可以开始下载的工作了。下面是通过顶角信息生成所有下载任务地址
然后就开启线程一个个下,没什么技术含量。
我的线程比较简单,没有做什么线程同步啊之类太专业的东西,
毕竟图片多一张少一张,大不了记录起来手工下载。

//拉取url线程
private void btnGetUrl_Click(object sender, EventArgs e)
{//生成URL链接CreateUrl();//获取URLThread t1 = new Thread(new ThreadStart(TaskRunBackgroundProcess));t1.IsBackground = true;t1.Start(); //启动线程t1
}

创建图片下载地址和保存地址,怎么计算地址的函数见下文
这里可以自己限制,下载的层数,我稍微贪心了点,就下载了几十万张,但是几乎用不到,自己掂量吧

//根据各层的最大最小值创建url
private void CreateUrl()
{PathUrlShouldSave.Clear();UrlShouldBeDownload_strList.Clear();UrlDownloaded_strList.Clear();UrlDownloadFailed_strList.Clear();for (int _level = 4; _level < levelCount; _level++){for (int _y = Level_map_y_min[_level]; _y < Level_map_y_max[_level]; _y++){for (int _x = Level_map_x_min[_level]; _x < Level_map_x_max[_level]; _x++){PathUrlShouldSave.Add(converPointToPathString(_x, _y, _level));UrlShouldBeDownload_strList.Add(converPointToUrlString(_x, _y, _level));}}}
}

创建拉取图片管理主线程,用于建立各个图片的拉取任务线程,(想象成迅雷就好了)。
一开始懒惰,开一条多线程,速度其慢,一个晚上没拉完,回来把线程开到20,一个小时的量差不多顶一个晚上,
但是20条线程,实际在用估计6-8条,其他都是轮不上的,傻等女神的屌丝线程。

//拉取图片线程
private void TaskRunBackgroundProcess()
{succeed = 0;displayState = "(" + Convert.ToString(succeed) + "/" + Convert.ToString(UrlShouldBeDownload_strList.Count) + ")";for (int i = 0; i < UrlShouldBeDownload_strList.Count; i++){try{int lastindex = PathUrlShouldSave[i].ToString().LastIndexOf("/");string path = PathUrlShouldSave[i].ToString().Substring(0, lastindex);Directory.CreateDirectory(path);while (threads > 20){Thread.Sleep(1);}Thread t2 = new Thread(new ParameterizedThreadStart(downloadProcess));t2.Start(i);}catch (System.Exception ex){MessageBox.Show(ex.ToString());}displayState = "(" + Convert.ToString(succeed) + "/" + Convert.ToString(UrlShouldBeDownload_strList.Count) + ")";}
}

单独一张图片的下载线程,通过i传递下载的是哪个单元的图片,有效抑制竞争关系。
毕竟唯一的资源唯一掌控是比较靠谱的

//下载一张图片的线程
private void downloadProcess(object i)
{int index = (int)i;threads++;try{using (System.Net.WebClient wc = new WebClient()){wc.Headers.Add("User-Agent", "Chrome");FileInfo fi = new FileInfo(PathUrlShouldSave[index].ToString());if (!fi.Exists)wc.DownloadFile(UrlShouldBeDownload_strList[index].ToString(), PathUrlShouldSave[index].ToString());}succeed++;}catch (System.Exception ex){UrlDownloadFailed_strList.Add(UrlShouldBeDownload_strList[index]);}threads--;
}

根据点坐标x y z计算出下载链接

        //点取出urlprivate string converPointToUrlString(int x, int y, int z){string strUrl = "";try{strUrl = string.Format("http://mt0.google.cn/vt/lyrs=m@241000000&hl=zh-CN&gl=CN&src=app&x={0}&y={1}&z={2}&s=Gali",x,y,z);}catch (System.Exception ex){MessageBox.Show(ex.ToString());}return strUrl;}

根据点坐标计算出保存的目录

        //点取出pathprivate string converPointToPathString(int x, int y, int z){string strUrl = "";try{strUrl = string.Format("E:/workspace2/BaiduMapTry/BaiduMapTry/Gmap/maptile/googlemaps/roadmap/{0}/{1}/{2}.png",z, x, y);}catch (System.Exception ex){MessageBox.Show(ex.ToString());}return strUrl;}

6.如何读取刚才保存的图片

把页面中js加载图片的目录计算成本地的目录,搞定

转载于:https://www.cnblogs.com/Again/p/3499385.html

2013年12月30日 星期一 谷歌、百度地图拽取相关推荐

  1. 每日小型简短新闻12条 11月30日 星期一

    [365资讯简报]每天一分钟,知晓天下事!2020年11月30日 星期一 农历十月十六 2021国考开考:拟招2.57万人,157万人过审,竞争比达61:1. 北方22城房价过万:前十中京津冀占一半, ...

  2. 【每日新闻早报简报】9月30日 星期一

    [每日新闻早报] 9月30日  星期一  农历九月初二 1.中国女排再现16年前辉煌,世界杯11战全胜夺第十个世界冠军,朱婷卫冕女排世界杯MVP!颜妮.王梦洁.丁霞入选最佳阵容: 2.商务部:刘鹤将率 ...

  3. 2008铁路旅客列车时刻表_重要消息!唐山站100多列旅客列车调整,12月30日起开始实行...

    自2019年12月30日零时起,唐山站旅客列车调整图实行.此次调图,唐山站合计调整列车102列,其中高速场38列.普速场64列.调图后唐山本站合计办理客运业务列车219列,普速场127列(较调图前减少 ...

  4. 个人空间岁末大回报活动12月30日获奖名单

    个人空间岁末大回报: 动手就有C币拿!活动已于15日启动,非常感谢各位网友的大力支持和积极参与,个人空间的所有工作人员在这祝大家好运,希望你们每天都能拿到C币存入社区银行! 欢迎各位获奖者去自己的银行 ...

  5. 【历史上的今天】12 月 30 日:C++ 之父诞生;Hotmail 创始人出生;Facebook 注册破百万

    整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来. 今天是 2021 年 12 月 30 日,在 1930 年的这一天,"青蒿素之母"屠呦呦出生.2015 ...

  6. 互联网晚报 | 12月30日 星期四 | 百度网盘青春版正式上线;汽车之家回应“年底大裁员”;A股年内成交额创历史新高...

    ‍ 今日看点 ✦ 腾讯微信支付支持全量商家小程序场景开通银联云闪付功能 ✦ 百度网盘青春版正式上线:免费空间10GB,支持无差别速率下载 ✦ 汽车之家:不存在大规模裁员,整体人员优化幅度不及5% ✦ ...

  7. 12月30日goCom社区OSGi Topic大纲和PPT

    12月30日下午13:00--15:00我将在普元goCom社区举行一次OSGi Topic,欢迎感兴趣的O粉(OSGi Fans)到时前往交流和讨论,由于这是在网上首次进行的公开Topic,鉴于对听 ...

  8. 鸿图之下服务器维护10月25,更新公告丨《鸿图之下》12月30日维护更新预告

    为了帮助大家更好地体验游戏,我们收集了大家的意见,并计划进行一次维护.此次维护将从12月30日凌晨5点00分开始,预计维护2小时.请各位主公提前安排游戏时间,稍作休息. 平衡性调整 调整张辽自带武技[ ...

  9. 紫禁繁花服务器维护一般多久,紫禁繁花手游2020年12月30日更新公告

    国力庆典活动即将开启!上线即可领取新服饰哦!那么本次版本更新了哪些有趣的内容呢?下面就让我们一起来看一下吧~! 紫禁繁花手游2020年12月30日更新公告 国力庆典活动 参与[国力庆典]活动 有机会获 ...

最新文章

  1. 直播预告|灵动MM32 MCU助力全国大学生智能汽车竞赛——基础培训
  2. Win7 PPTP/L2TP设置详细图解教程
  3. python最大值_Python 获取最大值函数|python3教程|python入门|python教程
  4. jbpm 和 drools_jBPM和Drools工作台中的用户和组管理
  5. 膜拜大佬!5年经验Android程序员面试27天,高级面试题+解析
  6. React开发(168):...dva调用不成功的原因
  7. 画图控件_用CAD画图,还不会用属性块?你不加班谁加班
  8. weblogic 调优参数
  9. 关于文件中的0D、0A
  10. linux emacs 快捷键,emacs常用快捷键
  11. 三万字带你了解那些年面过的Java八股文
  12. VeraCrypt文件硬盘加密使用教程
  13. FIFO设计中的注意问题与技巧
  14. 网易博客中的心情随笔
  15. 基于java的俄罗斯方块游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)
  16. latex 论文算法编辑
  17. DG(Data Guard)
  18. PyTorch (二):数据可视化 (TensorBoard、Visdom)
  19. php wrap,php wordwrap函数怎么用
  20. 初识AI,ML和DL关系

热门文章

  1. 为什么导出的CSV文件打开后是乱码?
  2. 关于获取来电显示的idea
  3. 大作狂潮来袭!E3部分参展PC游戏作品名单公
  4. 硕士论文查重系统应该如何选择?
  5. python枚举类的意义_python 枚举类型什么意思
  6. 三坐标检测之零件坐标系的建立原理
  7. 基于Python web框架Django+Bootstrap的房源推荐系统
  8. 两步搞定ubuntu18.04安装QQ,并实现屏幕共享,亲测
  9. 解决EasyExcel创建excel下拉框,下拉框内容过多时不显示的问题
  10. latex编译时报错:runaway argument?