1.数据来源:益动GPS
文章代码比较多,为了不吊人胃口,先看看最终效果:
[/code]
首先需要有原始数据信息,手机上众多跑步软件提供了详细的记录,但它们共同的问题是不允许自由导入导出(可能是为了用户粘性吧)。因此有一块智能运动手表应该是不二之选。我的是Garmin Fenix3,推荐一下:
益动GPS算是业界良心了,能够同步咕咚,Garmin手表,悦跑圈的数据,因此我将其作为一个入口,抓取所有的GPS数据。
至于如何同步,可参考网站上的相关介绍,下面是我登录该网站后的截图:
http://edooon.com/user/5699607196/record/15414378
随便点进去以后,就可以看到导出路线的按钮:
无比坑爹的是,它不提供批量导出的按钮,几百条记录,依次导出都累死了。于是考虑用代码来编辑吧。
2. 获取益动网站上的数据
登录之后,可以看出它是动态加载,当滚轮滚到最下时,自动加载后面的内容。本来是应该嗅探和分析http请求的,后来懒惰了。当拖到底,全部加载完毕后,保存了当前的html文件。
接下来就是解析这个Html,基本上是通过XPath的来做的。有经验的同学看了下图就都明白了:
图中高亮的部分,就是要下载gpx文件的实际地址。我们将其保存在urllist中。同时,元数据被保存在json文件里。
folder = u'D:/buptzym的同步盘/百度云/我的文档/数据分析/datasets/rungps/'; cookie='JSESSIONID=69DF607B71B1F14AFEC090F520B14B55; logincookie=5699607196$6098898D08E533587E82B33DD9D02196; persistent_cookie=5699607196$42C885AD38F59DCA407E09C95BE1A60B; uname_forloginform="buptzym@qq.com"; __utma=54733311.82935663.1447906150.1447937410.1456907433.7; __utmb=54733311.5.10.1456907433; __utmc=54733311; __utmz=54733311.1456907433.7.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; cookie_site=auto' userid='5699607196'; f = codecs.open(folder + 'desert.htm', 'r', 'utf-8'); html = f.read(); f.close(); root = etree.HTML(html) tree = etree.ElementTree(root); listnode=tree.xpath('//*[@id="feedList"]'); numre=re.compile(u'骑行|跑步|公里|,|耗时|消耗|大卡'); urllists=[] records=[]; for child in listnode[0].iterchildren(): record={}; temp=child.xpath('div[2]/div[1]/a[2]') if len(temp)==0: continue; source= temp[0].attrib['href']; record['id']=source.split('//m.sbmmt.com/m/')[-1]; info=temp[0].text; numinfo= numre.split(info); if len(numinfo)<6: continue; record['type']= info[0:2]; record['distance']= numinfo[1]; record['hot']=numinfo[6]; urllists.append('http://edooon.com/user/%s/record/export?type=gpx&id=%s' % (userid, record['id']));
值得注意的是,因为下载时需要cookie,因此读者需要将自己在益动GPS的userid和登录的cookie都替换掉。
接下来就是下载的过程,获取导出数据按钮的URL的XPath,构造一个带cookie的请求,然后保存文件即可,非常容易。
opener = urllib.request.build_opener() opener.addheaders.append(('Cookie', cookie)); path='//*[@id="exportList"]/li[1]/a'; for everyURL in urllists: id = everyURL.split('=')[-1]; print(id); url='http://edooon.com/user/%s/record/%s' % (userid, id); f = opener.open(url); html = f.read(); f.close(); root = etree.HTML(html) tree = etree.ElementTree(root); fs = str(tree.xpath(path)[0]); if fs is None: continue; furl = 'http://edooon.com/user/%s/record/%s' % (userid, fs); f = opener.open(furl); html = f.read(); f.close(); filename=folder+'id'+'.gpx'; xmlfile = codecs.open(filename, 'wb'); xmlfile.write(html); xmlfile.close();
之后,我们便保存了大约300多个gpx文件
3. 解析gpx数据
所谓gpx数据,是一种通用规范的GPS数据格式,详细的资料可自行搜索。
我们需要使用python的gpx解析器, gpxpy是个好选择,使用
pip3 install gpxpy 即可安装。
gpxpy提供了丰富的接口,当然为了统计,我们只需要提取一部分数据:
def readgpx(x): file= open(dir+x+'.gpx','r') txt=file.read() gpx=gpxpy.parse(txt) mv=gpx.get_moving_data() dat= {'移动时间':mv.moving_time,'静止时间':mv.stopped_time,'移动距离':mv.moving_distance,'暂停距离':mv.stopped_distance,'最大速度':mv.max_speed}; dat['总时间']=(gpx.get_duration()) dat['id']=str(x) updown=gpx.get_uphill_downhill() dat['上山']=(updown.uphill); dat['下山']=(updown.downhill) timebound=gpx.get_time_bounds(); dat['开始时间']=(timebound.start_time) dat['结束时间']=(timebound.end_time) p=gpx.get_points_data()[0] dat['lat']=p.point.latitude dat['lng']=p.point.longitude file.close() return dat
readgpx函数会读取文件名x,并将一个字典返回。并得到类似下面的一张表:
因为我们只需要绘制北京的区域,因此需要一个坐标表达式筛掉北京之外的地区。筛选代码使用了pandas,在附件里有更详细的代码。
exceptids=详细[(详细.lng<116.1)|(详细.lng>116.7)|(详细.lat<39.9)|(详细.lat>40.1)].id
def filtercity(r): sp=r.split('//m.sbmmt.com/m/')[-1].split('.') if sp[1]!='gpx': return False; if sp[0] in exceptids.values: return False; return True; bjids= [r for r in gpxs if filtercity(r)]
这样,我们就将所有在北京完成的运动数据筛选了出来。
4.绘制GPS数据
反复造轮子是不好玩的,绘制gpx已经有比较强大的库,地址在http://avtanski.net/projects/gps/
很不幸,这个库使用Perl作为开发语言,并使用了GD作为视觉渲染库。我花费了大量的时间,在安装GD上面。
Ubuntu默认安装Perl, GD是需要libgd的,libgd却在官网上极难下载,下载后却又发现版本不对,这让我在国外互联网上遨游了好几个小时,都要死掉了。。。到最后,我才发现,安装libgd库只要下面这一步就可以了:
apt-get install libgd-gd2-perl
我觉得这就是apt-get方式坑爹的地方,apt get gd 或者libgd根本找不到,如果不去查,谁知道这么写啊! 至于Perl的CPan管理工具,哎,不说了都是泪。
接下来下载gd 2.56,算是非常新的版本。找了各种中文版的安装步骤,发现都有问题。这种事情,最好的办法还是看README.MD啊!
解压之后,perl ./Makefile.PL
之后make
make install
然后就可以了。。。。。。
这份gpx绘制库是这么介绍自己的:
This folder contains several Perl scripts for processing and plotting
GPS track data in .GPX format. 它的readme有不少使用上的说明,当然我们不废话,把所有的gpx数据拷贝到sample_gpx文件夹下,然后华丽丽的运行 ./runme.sh 如果没有问题的话,应该是下面这样:
[/code
我假设各位读者对bash都已经很熟悉了,修改runme.sh文件,可查看更多的选项。 最后得到的结果如下图:
当时看到这个结果,我都惊呆了!这是自己跑了2000公里左右的结果,北京三环内(主要集中在长安街以北)主要的道路都遍了。尤其北三环和北土城路(10号线北段)被我各种虐。每一段白线都是一段故事,每一个点都是我的一个脚印啊!
5.总结
这文章写得显然不够详细,远远没有hand by hand。而且并没有提供更多的数据分析(显然这些工作我都做了)不过相信跑步的程序员一定都很厉害,我这就权作抛砖引玉了。
其实完全可以做成一个web服务,跑友们上传自己的跑步软件的id,就可以自动渲染出各种漂亮的跑步路径和分析图,应该会很有意义吧!
这件事情花费了我七八个小时,简直吐血,大量的时间用在了如何安装GD上,而不是下载数据上。教训告诉我,一定要读安装包里自带的说明文档,因为库和库之间的版本不同,因此可能造成版本地狱,到时候新版本卸载不了,老版本没法用的时候可别说我没提醒啊!
值得一提的是,益动gps下载的gpx文件不带换行符,这导致gpx_disualization库无法解析它(这货正则表达式写错了),我懒得再去动perl正则,于是通过替换增加了换行符。
以上是小编给大家介绍的Python和Perl绘制中国北京跑步地图的方法,希望对大家有所帮助!
![VIP课程(WEB全栈开发)](http://m.sbmmt.com/img/upload/course/000/000/071/628e00599d7e4913.png)
相关文章推荐
• 【腾讯云】年中优惠,「专享618元」优惠券!• 归纳总结Python函数进阶的使用方法• Python接口自动化测试必备基础之http协议详解• Python 3.11中的最佳新功能和功能修复• 实例详解Python面向对象的四大特征• Python数据分析之concat与merge函数(实例详解)独孤九贱(3)_JavaScript视频教程
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。
JavaScript教程125551次播放
独孤九贱(6)_jQuery视频教程
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。 核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。
jQuery教程103868次播放
jQuery与Ajax基础与实战
jQuery是最流行的JS函数库,封装了许多实用的功能,其中最引人入胜的就是Ajax。 jQuery中的Ajax操作,语法简单,操作方便,使Ajax从未如此轻松,前端人员从此不再为与服务器异步交互而发愁,本套课程,精选了最常用的几个方法,从基本的语法到每个参数,再到具体实例进行了全面的讲解。
AJAX教程4964次播放
Git教程(60分钟全程无废话版)
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持
JavaScript教程4281次播放