2012-06-19 3 views
6

Я новый пользователь linux/python и имею файлы .gpx (выходные файлы, созданные из программного обеспечения для отслеживания GPS), и вам нужно извлечь значения в csv/txt для использования в программе ГИС , Я искал строки и нарезки и т. Д. В моей начальной книге python, на этом веб-сайте и в Интернете. Я использовал конвертер .gpx в .txt и могу вытащить долготу и широту в текстовый файл. Мне нужно извлечь данные о высоте. Файл имеет шесть строк текста вверху, и я знаю только, как открыть этот файл в emacs (кроме загрузки на веб-сайт). Вот файл, начинающийся с строки 7.Как извлечь .gpx данные с помощью python

Оптимально, я хотел бы знать, как для извлечения всех значений через 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> 
+0

Из любопытства: Вы когда-нибудь понял, это вне? – simbabque

ответ

7

GPX is an XML format, поэтому использовать подходящий модуль, как lxml или включенный ElementTree XML API для синтаксического анализа данных, а затем вывода в CSV, используя Python csv module.

Учебники охватывающих эти понятия:

Я также нашел разборе библиотеки питона GPX называется gpxpy, что, возможно, дает более высокого уровень интерфейс к данным, содержащимся в файлах GPX.

+0

Я попробую. Кто-то также предложил мне, что Perl может быть способом извлечь их. Поскольку я в равной степени новичок для обоих, я сначала рассмотрю ваши упомянутые учебники. Спасибо, Мартийн! –

+0

Perl будет одинаково подходит для задачи; есть Perl XML-синтаксические анализаторы и CSV-библиотеки, как и для python. Однако вы можете легко найти Python; по моему личному мнению, Perl слишком легко переходит в линейный шум. –

+0

Пользуюсь твоим словом, спасибо! –

6

Поскольку 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; 

Давайте это ступенчато:

  • use strict и use warnings соблюдение правил, как декларирование переменных и рассказать вам о наиболее распространенных ошибках, которые труднее всего найти.
  • use Geo::Gpx и use DateTime - модули, которые мы используем. Geo::Gpx будет обрабатывать синтаксический анализ для нас. Нам нужно DateTime, чтобы сделать отметки времени unix в считанные даты и время.
  • Функция open открывает файл. $fh_in - это переменная, содержащая дескриптор файла. Файл GPX, который мы хотим прочитать, - fells_loop.gpx, который я взял на себя взаймы от topografix.com. Вы можете найти дополнительную информацию об open в perlopentut.
  • Мы создаем новый объект Geo::Gpx под названием $gpx и используем нашу файловую дескриптор $fh_in, чтобы сообщить ему, где читать данные XML. Метод new предоставляется всеми модулями Perl, которые имеют объектно-ориентированный интерфейс.
  • close закрывает дескриптор файла.
  • В следующем open есть >, чтобы сообщить Perl, что мы хотим записать в этот файл.
  • Мы отправили print в файл дескриптор, поставив его в качестве первого аргумента print. Обратите внимание, что после дескриптора файла нет запятой. \n - символ новой строки.
  • foreach loop принимает возвращаемое значение 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' 
        }; 
    
  • Теперь постфиксаfor немного сложнее. Как мы только что видели, в hashref есть 8 ключей. К сожалению, некоторые из них иногда отсутствуют. Поскольку у нас есть use warnings, мы получим предупреждение, если попытаемся получить доступ к одному из этих отсутствующих значений. Мы должны создать эти ключи и поставить пустую строку ''.

    foreach и for полностью взаимозаменяемы в Perl, и оба могут быть также использованы в постфиксе синтаксиса позади одного выражения. Мы используем qw -оператор для создания списка, который for будет выполнять итерацию. qw не подходит для цитируемых слов, и он делает именно это: он возвращает список строк в нем, но цитируется. Мы могли бы также сказать ('time', 'lat', 'long'...).

    В выражении мы получаем доступ к каждой клавише $wp. $_ - это переменная цикла. На первой итерации она будет содержать «время», затем «лат» и т. Д. Поскольку $wp является hashref, нам нужны -> для доступа к его ключам. Кудрявые скобки говорят, что это hashref. ||= operator присваивает значение нашему элементу хэша ref только в том случае, если он не является истинным значением.

  • Теперь, если есть значение времени (пустая строка, которую мы только что назначили, если дата не была установлена, считается «нет»), мы заменяем временную метку unix соответствующей датой. DateTime помогает нам в этом. Метод from_epoch получает временную метку unix в качестве аргумента. Он возвращает объект DateTime, который мы можем напрямую использовать для вызова функции iso8601.

    Это называется цепью. Некоторые модули могут это сделать. Это похоже на то, что делают объекты JavaScript jQuery. Временная метка unix в нашем hashref заменяется результатом операции DateTime.

  • Теперь мы print в наш файл снова. join используется для помещения запятых между значениями. Мы снова добавим новую строку в конец.
  • Как только мы закончим с петлей, мы делаем close filehandle.
  • Теперь все готово! :)

В целом, я бы сказал, что это довольно просто и также вполне читаемо, не так ли? Я попытался сделать это здоровым сочетанием чрезмерно подробного синтаксиса с ароматом _Perl_ish.

+0

Спасибо за ваш скрипт! Я пошел в CPAN, посмотрел @ readme и получил ошибки. команда perl Makefile.PL привела к: Необязательному ExtUtils :: MakeMaker :: Покрытие недоступно Аргумент «6.57_05» не является числовым в числовом ge (> =) в строке Makefile.PL 34. Проверьте, завершен ли ваш комплект. .. Хорошо выглядит Предупреждение: предварительное условие DateTime :: Format :: ISO8601 0 не найден. Предупреждение: предпосылка HTML :: Объекты 0 не найдены. Предупреждение: предпосылка XML :: Спуск 1.01 не найден. Написание Makefile для Geo :: Gpx Написание MYMETA.yml продолжалось с помощью теста test & 8/10 и 3/3 подтестов. попытался запустить только lat, lon, elev, w/noluck –

+0

, поэтому у меня есть 4 страницы ошибок из теста make, хотя и пытались удалить время и все другие поля из текста, кроме lat, lon, elev и запустить его в любом случае, без везения. Вчера я прочитал свои первые 3 главы начальной книги perl, поэтому я надеюсь, что это будет легко и просто исправлено. Я также попытался переустановить под sudo без везения. сценарий имеет смысл, и я также ценю часть объяснения. Будучи новичком, я сейчас царапаю голову. –

+0

Вы прочитали руководство по [установке модулей cpan] (http://www.cpan.org/modules/INSTALL.html)? Или вы пытались загрузить его с сайта CPAN? Если вы используете инструмент командной строки, он установит все зависимости. – simbabque

3

Вы можете установить GPXpy

sudo pip install gpxpy 

Затем просто использовать библиотеку:

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:' 

Для получения дополнительной информации: https://pypi.python.org/pypi/gpxpy

С уважением

Смежные вопросы