OpenStreetMap Forum

The Free Wiki World Map

You are not logged in.

#1 2010-10-23 09:27:11

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

perl + .osm

Есть .osm-файл со списком городов.

Есть perl с perl-XML-Parser

Как на выходе получить список названий городов и их статусов?

Дайте, плиз, пример такого скриптика, потому что ни разу с хмл-ем не работал, я его покручу и буду дальше усложнять.

Offline

#2 2010-10-23 09:42:05

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

use Geo::Parse::OSM;

Geo::Parse::OSM->parse_file( 'file.osm', sub { print "$_[0]->{tag}->{place} $_[0]->{tag}->{name}\n" if $_[0]->{tag}->{place} eq 'town' } );

Offline

#3 2010-10-23 10:14:33

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Так, вроде даже получилось модуль установить и запустить smile

А чой-то он ругается на юникод, как это побороть?

Wide character in print at ./test_osm.pl line 5, <GEN0> line 5524.
town Vrbno pod Pradědem
town Lomnice nad Popelkou
Wide character in print at ./test_osm.pl line 5, <GEN0> line 5538.
town Meziboří

Offline

#4 2010-10-23 10:16:06

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

установи выходную кодировку.
binmode STDOUT, ':utf8';
или
binmode STDOUT, ':encoding(cp866)';

Offline

#5 2010-10-23 10:26:38

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Ну, вроде заработало!

Будем дальше думать что с этим делать smile

Offline

#6 2010-10-23 13:31:24

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Хочу из википедии вытащить статью про город, но получаю ошибку от википедии о неправильном названии статьи (недопустимые символы)

#!/usr/bin/perl

use WWW::Wikipedia;

my $wikientry = "Яблонец-над-Нисоу";
my $wiki = WWW::Wikipedia->new(language => 'ru');
my $entry = $wiki->search( $wikientry );
my $entry_ru = $entry->language( 'ru' );
print $entry_ru->raw();

Как превратить "Яблонец-над-Нисоу" в "%D0%AF%D0%B1%D0%BB%D0%BE%D0%BD%D0%B5%D1%86-%D0%BD%D0%B0%D0%B4-%D0%9D%D0%B8%D1%81%D0%BE%D1%83"? Мне кажется именно в этом проблема, потому что статью "Perl" нормально обрабатывает.

Offline

#7 2010-10-23 13:57:29

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

use utf8;

и сохранить исходник в этом utf8

Offline

#8 2010-10-23 14:29:56

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Чота всё равно не работает.

#!/usr/bin/perl

use utf8;
use URI::Escape;
use WWW::Wikipedia;

# binmode STDOUT, ':utf8';

my $wikientry = "Яблонец-над-Нисоу";
my $wikientry_safe = uri_escape_utf8($wikientry)."\n";
my $wiki = WWW::Wikipedia->new(language => 'ru');
my $entry = $wiki->search( $wikientry_safe );
# print $entry->text();

# print "\n\n===\n\n";

my $entry_ru = $entry->language( 'ru' );
print $entry_ru->raw();

Вместо сырого текста статьи возвращает хтмл-страницу с ошибкой.

Исходник у меня и так в утф-8

Offline

#9 2010-10-23 14:42:49

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

Тогда писать багрепорт на WWW:Wikipedia, а пока заурленкодить руками. Но надо понять, что именно ему не нравится

Offline

#10 2010-10-23 14:51:34

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

liosha, а ты можешь проверить, так же оно ошибку выдаёт?

Offline

#11 2010-10-23 15:19:12

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

Доберусь до дома - посмотрю
Кстати, совершенно не понял, зачем там uri_escape, да ещё и с \n. Всё должно работать без него.

Offline

#12 2010-10-23 15:35:15

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Похоже я что-то перемудрил там smile

Сделал тотальный рефакторинг, всё заработало...

#!/usr/bin/perl

use WWW::Wikipedia;

my $wikientry = "Яблонец-над-Нисоу";
my $wiki = WWW::Wikipedia->new( language => 'ru');
my $entry = $wiki->search( $wikientry );
print $entry->raw();

Offline

#13 2010-10-23 15:49:13

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Можно ещё глупый вопрос?

В $entry->raw(); получаем одним куском текст с переносами строк. Как этот кусок обработать построчно?

Offline

#14 2010-10-23 15:54:08

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

split "\r\n", $entry->raw()

Offline

#15 2010-10-23 16:08:44

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Лучше я сразу скажу что хочу получить smile

Я получаю сырой текст статьи, в котором есть в конце строки типа:

...
{{нет иллюстраций}}
{{cz-geo-stub}}
[[Категория:Яблонец-над-Нисоу|*]]


[[cs:Jablonec nad Nisou]]
[[de:Jablonec nad Nisou]]
[[dsb:Jablonec nad Nisou]]
[[en:Jablonec nad Nisou]]
[[eo:Jablonec nad Nisou]]
[[es:Jablonec nad Nisou]]
[[fr:Jablonec nad Nisou]]
...

Мне надо из строки по коду
[[cs:.+]]
Получить
Jablonec nad Nisou

Может регексп можно на весь текст напустить, но я пока не соображу как.

...
my $rawtext = $entry->raw()."\n";
$rawtext =~ s/[[cs:(.+)]]/\1/m;
print $rawtext;

Возвращает весь текст целиком.

После недолгого перерыва в общении с перлом все навыки выветриваются, и похоже я туплю smile

Offline

#16 2010-10-23 16:18:59

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

my ($cs) = $rawtext =~ /\[cs:([^\[]+)\]/;

Offline

#17 2010-10-23 16:26:28

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Во! Спасибо, работает!

А то я чота типа такого намалевал: $rawtext =~ s/.*\[\[cs:(\w+)\]\].*/\1/s;

Разные вариации либо весь текст оставляют, либо от нужного места до конца, либо вообще всё съедается. smile

Offline

#18 2010-10-23 17:37:02

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Так, теперь у меня есть осм-файл с более 600 чешских городов, плюс список соответствия чешских и русских названий чуть более сотни городов, взятый из википедии:

Прага:Praha
Брно:Brno
Острава:Ostrava
Пльзень:Plzeň
Либерец:Liberec
Оломоуц:Olomouc
Усти-над-Лабем:Ústí nad Labem
Градец-Кралове:Hradec Králové
Ческе-Будеёвице:České Budějovice
Пардубице:Pardubice
Гавиржов:Havířov
Злин:Zlín
Кладно:Kladno
Мост (город):
Карвина:Karviná
Фридек-Мистек:Frýdek-Místek
Опава:Opava
Карлови-Вари:
Теплице:Teplice
Дечин:Děčín
Йиглава:Jihlava
Хомутов (город):
Пршеров:Přerov
Яблонец-над-Нисоу:Jablonec nad Nisou
Простеёв:Prostějov
Млада-Болеслав:Mladá Boleslav
Ческа-Липа:Česká Lípa
Тршебич:Třebíč
Тршинец:Třinec
Табор (город):Tábor
Абертамы:
Адамов (район Бланско):Adamov (okres Blansko)
Аш:Aš
Бенешов:Benešov
Бероун:Beroun
Брно:Brno
Всетин:Vsetín
Вишков:Vyškov
Гавиржов:Havířov
Гавличкув-Брод:Havlíčkův Brod
Глучин:Hlučín
Годонин:Hodonín
Градец-Кралове:Hradec Králové
Двур-Кралове:
Дечин:Děčín
Дивишов:Divišov
Домажлице:Domažlice
Есеник:Jeseník
Жатец:Žatec
Железна-Руда:Železná Ruda
Злин:Zlín
Зноймо:Znojmo
Йиглава:Jihlava
Йиндржихув-Градец:Jindřichův Hradec
Йичин:Jičín
Карвина:Karviná
Карловы Вары:Karlovy Vary
Кашперске-Гори:Kašperské Hory
Кинжварт:
Кладно:Kladno
Клатови:Klatovy
Колин:Kolín
Коуржим:Kouřim
Кралупи:
Крнов:Krnov
Кутна-Гора:Kutná Hora
Лазне-Богданеч:Lázně Bohdaneč
Ланшкроун:Lanškroun
Летоград:Letohrad
Либерец:Liberec
Либице:
Литомержице:Litoměřice
Литомышль:
Лоуни:Louny
Лугачовице:Luhačovice
Марианске-Лазне:Mariánské Lázně
Мельник (город):Mělník
Миловице:Milovice
Мирослав (город):Miroslav (okres Znojmo)
Млада-Болеслав:Mladá Boleslav
Мнихово-Градиште:Mnichovo Hradiště
Мост (город):
Мшено:Mšeno
Нимбурк:Nymburk
Нови-Йичин:Nový Jičín
Оломоуц:Olomouc
Опава:Opava
Острава:Ostrava
Пардубице:Pardubice
Писек:Písek (město)
Пльзень:Plzeň
Подебради:Poděbrady
Прага:Praha
Пршебуз:Přebuz
Пршибислав:Přibyslav
Пршибор:Příbor (okres Nový Jičín)
Пршибрам:Příbram
Рожмберк-над-Влтавоу:Rožmberk nad Vltavou
Раковник:Rakovník
Рокицани:Rokycany
Роуднице-над-Лабем:Roudnice nad Labem
Свитави:Svitavy
Седлец-Прчице:Sedlec-Prčice
Славков-у-Брна:Slavkov u Brna
Соколов (город):
Страконице:Strakonice
Табор (город):Tábor
Тахов:Tachov
Телч:
Теплице:Teplice
Терезин:Terezín
Трутнов:Trutnov
Тршебич:Třebíč
Тршебонь:Třeboň
Тршинец:Třinec
Усти-над-Лабем:Ústí nad Labem
Усти-над-Орлици:Ústí nad Orlicí
Франтишкови-Лазне:Františkovy Lázně
Фридек-Мистек:Frýdek-Místek
Фридлант:Frýdlant
Фульнек:Fulnek
Хеб:Cheb
Хомутов (город):
Хрудим:Chrudim
Ческа Липа:
Ческе-Будеёвице:České Budějovice
Чески-Крумлов:Český Krumlov
Чески-Тешин:Český Těšín
Шлукнов:Šluknov
Шумперк:Šumperk
Яблонец-над-Нисоу:Jablonec nad Nisou

Как теперь это всё залить в name:ru ?

Offline

#19 2010-10-23 17:45:20

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

Что-то типа

use Geo::Parse::OSM;

my $addname = sub {
    if ( ... ) {
        $_[0]->{action} = 'modify';
        $_[0]->{tag}->{'name:ru'} = ...;
        print Geo::Parse::OSM->to_xml( $_[0] );
    } 
};

print "<osm>\n";
Geo::Parse::OSM->parse_file( 'file.osm', $addname );
print "</osm>\n";

Offline

#20 2010-10-23 18:03:31

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Хм... Выглядит вроде несложно smile

А что будет если попытаться добавить существующий тег с точно таким же значением?

Offline

#21 2010-10-23 18:05:01

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

Поменяет

Offline

#22 2010-10-23 19:18:01

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

Написал вроде. Остался косяк с юникодом.

Если я не делаю binmode STDOUT, ':utf8'; , то получается
    <tag k="name" v="Opava"/>
    <tag k="name:ru" v="Ðпава"/>

Если делаю, то
    <tag k="name" v="Opava"/>
    <tag k="name:ru" v="ÃÂÿðòð"/>

Без binmode нормально работают обычные принты в стдаут, но не работает
print Geo::Parse::OSM->to_xml( $_[0] );

С binmode портится что-то другое.

Что делать-то?

Консоль у меня юникодная
[ilis@altus osm_perl]$ locale
LANG=ru_RU.UTF-8

ЗЫ. И сравнение не работает если в чешском нейме есть гачеки (умляуты их).

        $csname = $_[0]->{tag}->{'name'};
        if ( $hash{$csname} ne '' && $_[0]->{tag}->{'name:ru'} eq '') {

Last edited by Ilis (2010-10-23 19:23:13)

Offline

#23 2010-10-23 19:24:44

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

to_xml отдаёт уже готовый utf8, дополнительный фильтр не требуется.
Пиши его в отдельный файл.
Или если нужно именно с фильтром, то print decode( 'utf8', Geo::Parse::OSM->to_xml( $_[0] ) );

Offline

#24 2010-10-23 19:28:33

Ilis
Member
From: Екатеринбург
Registered: 2009-05-24
Posts: 5,970

Re: perl + .osm

liosha wrote:

to_xml отдаёт уже готовый utf8, дополнительный фильтр не требуется.
Пиши его в отдельный файл.
Или если нужно именно с фильтром, то print decode( 'utf8', Geo::Parse::OSM->to_xml( $_[0] ) );

Может он его там два раза отдаёт?

И что делать со сравнением? Из сотни городов только полтора десятка отбираются.

Offline

#25 2010-10-23 19:31:13

liosha
Member
From: Moscow
Registered: 2008-03-04
Posts: 8,447
Website

Re: perl + .osm

Где-то теряешь кодировку. Где именно, вслепую угадать сложно  smile

Offline

Board footer

Powered by FluxBB