如何用python提取.gpx数据

Pau*_* M. 10 python perl extract gpx

我是一个新的linux/python用户,有.gpx文件(由GPS跟踪软件制作的输出文件),需要将值提取到csv/txt中,以便在GIS程序中使用.我已经在我开始的python书,本网站和在线查找了字符串和切片等.我使用了.gpx到.txt转换器,可以将经度和纬度拉出到文本文件中.我需要提取高程数据.该文件在顶部有六行文本,我只知道如何在emacs中打开此文件(除了在网站上传)这是从第7行开始的文件.

最理想的是,我想知道如何通过python(或Perl)将所有值提取到csv或txt文件中.如果有人知道网站教程或示例脚本,将不胜感激.

<metadata>
<time>2012-06-13T01:51:08Z</time>
</metadata>
<trk>
<name>Track 2012-06-12 19:51</name>
<trkseg>
<trkpt lat="43.49670697" lon="-112.03380961">
<ele>1403.0</ele>
<time>2012-06-13T01:53:44Z</time>
<extensions>
<ogt10:accuracy>34.0</ogt10:accuracy></extensions>
</trkpt>
<trkpt lat="43.49796612" lon="-112.03970968">
<ele>1410.9000244140625</ele>
<time>2012-06-13T01:57:10Z</time>
<extensions>
<gpx10:speed>3.75</gpx10:speed>
<ogt10:accuracy>13.0</ogt10:accuracy>
<gpx10:course>293.20001220703125</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49450857" lon="-112.04477274">
<ele>1406.5</ele>
<time>2012-06-13T02:02:24Z</time>
<extensions>
<ogt10:accuracy>12.0</ogt10:accuracy></extensions>
</trkpt>
</trkseg>
<trkseg>
<trkpt lat="43.49451057" lon="-112.04480354">
<ele>1398.9000244140625</ele>
<time>2012-06-13T02:54:55Z</time>
<extensions>
<ogt10:accuracy>10.0</ogt10:accuracy></extensions>
</trkpt>
<trkpt lat="43.49464813" lon="-112.04472215">
<ele>1414.9000244140625</ele>
<time>2012-06-13T02:56:06Z</time>
<extensions>
<ogt10:accuracy>7.0</ogt10:accuracy></extensions>
</trkpt>
<trkpt lat="43.49432573" lon="-112.04489684">
<ele>1410.9000244140625</ele>
<time>2012-06-13T02:57:27Z</time>
<extensions>
<gpx10:speed>3.288236618041992</gpx10:speed>
<ogt10:accuracy>21.0</ogt10:accuracy>
<gpx10:course>196.1999969482422</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49397445" lon="-112.04505216">
<ele>1421.699951171875</ele>
<time>2012-06-13T02:57:30Z</time>
<extensions>
<gpx10:speed>3.0</gpx10:speed>
<ogt10:accuracy>17.0</ogt10:accuracy>
<gpx10:course>192.89999389648438</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49428702" lon="-112.04265923">
<ele>1433.0</ele>
<time>2012-06-13T02:58:46Z</time>
<extensions>
<gpx10:speed>4.5</gpx10:speed>
<ogt10:accuracy>18.0</ogt10:accuracy>
<gpx10:course>32.400001525878906</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49444603" lon="-112.04263691">
<ele>1430.199951171875</ele>
<time>2012-06-13T02:58:50Z</time>
<extensions>
<gpx10:speed>4.5</gpx10:speed>
<ogt10:accuracy>11.0</ogt10:accuracy>
<gpx10:course>29.299999237060547</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49456961" lon="-112.04260058">
<ele>1430.4000244140625</ele>
<time>2012-06-13T02:58:52Z</time>
<extensions>
<gpx10:speed>4.5</gpx10:speed>
<ogt10:accuracy>8.0</ogt10:accuracy>
<gpx10:course>28.600000381469727</gpx10:course></extensions>
</trkpt>
<trkpt lat="43.49570131" lon="-112.04001132">
<ele>1418.199951171875</ele>
<time>2012-06-13T03:00:08Z</time>
<extensions>
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 9

GPX是一种XML格式,因此使用像lxml这样的拟合模块或包含的ElementTree XML API来解析数据,然后使用python csv模块输出到CSV .

涵盖这些概念的教程:

我还发现了一个名为gpxpy的python GPX解析库,它可能为GPX文件中包含的数据提供了更高级别的接口.


sim*_*que 7

由于Martijn发布了一个Python回答,并说Perl会转向线路噪音,我觉得还需要一个Perl答案.

CPAN上,Perl模块目录中有一个名为Geo :: Gpx的模块.正如Martijn所说,GPX是一种XML格式.但幸运的是,有人已经将它变成了一个处理我们解析的模块.我们所要做的就是加载该模块.

有几个模块可用于CSV处理,但此XML文件中的数据相当简单,因此我们并不需要一个.我们可以通过内置功能自行完成.

请考虑以下脚本.我会在一分钟内给出解释.

use strict;
use warnings;
use Geo::Gpx;
use DateTime;
# Open the GPX file
open my $fh_in, '<', 'fells_loop.gpx';
# Parse GPX
my $gpx = Geo::Gpx->new( input => $fh_in );
# Close the GPX file
close $fh_in;

# Open an output file
open my $fh_out, '>', 'fells_loop.csv';
# Print the header line to the file
print $fh_out "time,lat,lon,ele,name,sym,type,desc\n";

# The waypoints-method of the GEO::GPX-Object returns an array-ref
# which we can iterate in a foreach loop
foreach my $wp ( @{ $gpx->waypoints() } ) {
  # Some fields seem to be optional so they are missing in the hash.
  # We have to add an empty string by iterating over all the possible
  # hash keys to put '' in them.
  $wp->{$_} ||= '' for qw( time lat lon ele name sym type desc );

  # The time is a unix timestamp, which is hard to read.
  # We can make it an ISO8601 date with the DateTime module.
  # We only do it if there already is a time, though.
  if ($wp->{'time'}) {
    $wp->{'time'} = DateTime->from_epoch( epoch => $wp->{'time'} )
                             ->iso8601();
  }
  # Join the fields with a comma and print them to the output file
  print $fh_out join(',', (
    $wp->{'time'},
    $wp->{'lat'},
    $wp->{'lon'},
    $wp->{'ele'},
    $wp->{'name'},
    $wp->{'sym'},
    $wp->{'type'},
    $wp->{'desc'},
  )), "\n"; # Add a newline at the end
}
# Close the output file
close $fh_out;
Run Code Online (Sandbox Code Playgroud)

让我们分步吧:

  • use strictuse warnings强制执行规则,如声明变量,并告诉您最难找到的常见错误.
  • use Geo::Gpx并且use DateTime是我们使用的模块.Geo::Gpx将为我们处理解析.我们需要DateTime将unix时间戳设置为可读日期和时间.
  • open函数打开一个文件.$fh_in是保存文件句柄的变量.我们想要阅读的GPX文件是fells_loop.gpx,我冒昧从topografix.com借用.你可以openperlopentut找到更多信息.
  • 我们创建一个Geo::Gpx名为的新对象,$gpx并使用我们的文件句柄$fh_in告诉它从哪里读取XML数据.该new-method由具有面向对象接口的所有Perl模块提供.
  • close 关闭文件句柄.
  • 接下来open有一个>要告诉Perl我们要写入该文件句柄.
  • 我们print将它作为第一个打印参数放到文件句柄中.请注意,文件句柄后没有逗号.这\n是一个换行符.
  • foreach取的返回值waypoints的的-方法Geo::Gpx的对象.该值是数组引用.可以把它想象成一个包含数组的数组(如果你想了解更多有关引用的信息,请参阅perlref).在循环的每次迭代中,将放入该数组ref的下一个元素(表示GPX数据中的一个航点)$wp.如果用Data::Dumper它打印,看起来像这样:

    $VAR1 = {
          'ele' => '64.008000',
          'lat' => '42.455956',
          'time' => 991452424,
          'name' => 'SOAPBOX',
          'sym' => 'Cemetery',
          'desc' => 'Soap Box Derby Track',
          'lon' => '-71.107483',
          'type' => 'Intersection'
        };
    
    Run Code Online (Sandbox Code Playgroud)
  • 现在后缀 for有点棘手.正如我们刚才看到的,hashref中有8个键.不幸的是,其中一些有时会丢失.因为我们有use warnings,如果我们尝试访问其中一个缺失值,我们会收到警告.我们必须创建这些键并''在其中放置一个空字符串.

    foreach并且for在Perl中完全可以互换,并且两者也可以在单个表达式后面的后缀语法中使用.我们使用qw-operator来创建for将迭代的列表.qw引用单词的缩写,它只是这样:它返回一个字符串列表,但引用.我们也可以说('time', 'lat', 'long'... ).

    在表达式中,我们访问每个键$wp.$_是循环变量.在第一次迭代中,它将保持"时间",然后是"纬度",依此类推.由于$wp是hashref,我们需要->访问它的密钥.花括号告诉它是一个hashref.仅当||=运算符不是真值时,运算符才会为哈希引用元素赋值.

  • 现在,如果有一个时间值(如果未设置日期,我们刚刚分配的空字符串被视为'没有'),我们将unix时间戳替换为正确的日期.DateTime帮助我们做到这一点.该from_epoch方法将unix时间戳作为参数.它返回一个DateTime对象,我们可以直接用它来调用iso8601它上面的函数.

    这称为链接.有些模块可以做到.它类似于jQuery的JavaScript对象.我们的hashref中的unix时间戳被替换为DateTime操作的结果.

  • 现在我们print再来一次文件句柄.join用于在值之间放置逗号.我们还在最后添加了换行符.
  • 一旦我们完成循环,我们close就是文件句柄.
  • 现在我们完成了!:)

总而言之,我会说这很简单,也很可读,不是吗?我试图将它过于冗长详细的语法和_Perl_ish风格的健康混合.


Cha*_* P. 6

您可以安装GPXpy

sudo pip install gpxpy
Run Code Online (Sandbox Code Playgroud)

然后只需使用库:

import gpxpy 
import gpxpy.gpx 

 gpx_file = open('input_file.gpx', 'r') 

    gpx = gpxpy.parse(gpx_file) \
    for track in gpx.tracks: 
      for segment in track.segments: 
    for point in segment.points: 
      print 'Point at ({0},{1}) -> {2}'.format(point.latitude, point.longitude, point.elevation) 

    for waypoint in gpx.waypoints: 
      print 'waypoint {0} -> ({1},{2})'.format(waypoint.name, waypoint.latitude, waypoint.longitude) 

    for route in gpx.routes: 
      print 'Route:' 
Run Code Online (Sandbox Code Playgroud)

有关更多信息:https : //pypi.python.org/pypi/gpxpy

问候

  • `sudo pip` 几乎从来都不是一个好主意(例如参见[this](https://askubuntu.com/questions/802544/is-sudo-pip-install-still-a-broken-practice))。 (4认同)