Python和Perl繪製中國北京跑步地圖的方法

來源:互聯網
上載者:User
當你在一個城市,穿越大街小巷,跑步跑了幾千公裡之後,一個顯而易見的想法是,我到底和之前比快了多少,跑量有何變化,如果能把在這個城市的所有路線全部畫出來,會是怎樣的景象呢?

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('/')[-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.latitudedat['lng']=p.point.longitudefile.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('/')[-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庫無法解析它(這貨Regex寫錯了),我懶得再去動perl正則,於是通過替換增加了分行符號。

以上是小編給大家介紹的Python和Perl繪製中國北京跑步地圖的方法,希望對大家有所協助!

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.