From 50ac58e8ebae424bc66c593afac14954c1475e19 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Wed, 22 Jun 2011 19:57:16 +0200 Subject: Travel::Status::DE::DeutscheBahn --- .gitignore | 9 ++ Build.PL | 25 ++++ bin/mris | 127 ++++-------------- lib/Travel/Status/DE/DeutscheBahn.pm | 170 +++++++++++++++++++++++++ lib/Travel/Status/DE/DeutscheBahn/Departure.pm | 69 ++++++++++ lib/Travel/Status/DeutscheBahn.pm | 65 ---------- 6 files changed, 301 insertions(+), 164 deletions(-) create mode 100644 .gitignore create mode 100755 Build.PL create mode 100644 lib/Travel/Status/DE/DeutscheBahn.pm create mode 100644 lib/Travel/Status/DE/DeutscheBahn/Departure.pm delete mode 100644 lib/Travel/Status/DeutscheBahn.pm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8f36dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/_build +/Build +/blib +/cover_db +/MANIFEST +/MANIFEST.bak +/MANIFEST.SKIP +/MANIFEST.SKIP.bak +/MYMETA.yml diff --git a/Build.PL b/Build.PL new file mode 100755 index 0000000..8dd5215 --- /dev/null +++ b/Build.PL @@ -0,0 +1,25 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Module::Build; + +Module::Build->new( + + build_requires => { + 'Test::More' => 0, + 'Test::Compile' => 0, + 'Test::Pod' => 0, + }, + module_name => 'Travel::Status::DE::DeutscheBahn', + license => 'perl', + requires => { + 'perl' => '5.10.0', + 'Class::Accessor' => '0.16', + 'LWP::UserAgent' => 0, + 'XML::LibXML' => '1.70', + }, + script_files => 'bin/', + sign => 1, + +)->create_build_script(); diff --git a/bin/mris b/bin/mris index 06b6483..c6e34c7 100755 --- a/bin/mris +++ b/bin/mris @@ -1,130 +1,55 @@ #!/usr/bin/env perl -## Copyright © 2010 by Daniel Friesel -## License: WTFPL -## 0. You just DO WHAT THE FUCK YOU WANT TO. use strict; use warnings; use 5.010; -use LWP::UserAgent; -use XML::LibXML; - -my @now = localtime(time()); -my $date = sprintf("%d.%d.%d", $now[3], $now[4] + 1 , $now[5] + 1900); -my $time = sprintf("%d:%d", $now[2], $now[1]); - -my $post = { - input => $ARGV[0], - inputRef => '#', - date => $date, - time => $time, - productsFilter => '1111101000000000', - REQTrain_name => q{}, - maxJourneys => 20, - delayedJourney => undef, - start => 'Suchen', - boardType => 'Abfahrt', - ao => 'yes', -}; - -my $ua = LWP::UserAgent->new(); -my $reply = $ua->post('http://mobile.bahn.de/bin/mobil/bhftafel.exe/dn?rt=1', $post)->content(); - -my $tree = XML::LibXML->load_html( - string => $reply, - recover => 2, - suppress_errors => 1, - suppress_warnings => 1, -); - -my $xp_element = XML::LibXML::XPathExpression->new('//table[@class="result stboard dep"]/tr'); -my $xp_time = XML::LibXML::XPathExpression->new('./td[@class="time"]'); -my $xp_train = XML::LibXML::XPathExpression->new('./td[@class="train"]'); -my $xp_route = XML::LibXML::XPathExpression->new('./td[@class="route"]'); -my $xp_dest = XML::LibXML::XPathExpression->new('./td[@class="route"]//a'); -my $xp_platform = XML::LibXML::XPathExpression->new('./td[@class="platform"]'); -my $xp_info = XML::LibXML::XPathExpression->new('./td[@class="ris"]'); - -my $re_via = qr{ - ^ (.+) \n - \d{1,2}:\d{1,2} -}mx; - -for my $tr (@{$tree->findnodes($xp_element)}) { - - my ($n_time) = $tr->findnodes($xp_time); - my (undef, $n_train) = $tr->findnodes($xp_train); - my ($n_route) = $tr->findnodes($xp_route); - my ($n_dest) = $tr->findnodes($xp_dest); - my ($n_platform)= $tr->findnodes($xp_platform); - my ($n_info) = $tr->findnodes($xp_info); - my $first = 1; - - if (not ($n_time and $n_dest)) - { - next; - } +our $VERSION = '0.0'; - my $time = $n_time->textContent(); - my $train = $n_train->textContent(); - my $route = $n_route->textContent(); - my $dest = $n_dest->textContent(); - my $platform = $n_platform->textContent(); - my $info = $n_info->textContent(); - my $via_str; - my (@via, @via_main, @via_show); - - for my $str ($time, $train, $dest, $platform, $info) { - $str =~ s/\n//mg; - $str =~ tr/ //s; - } +use Travel::Status::DE::DeutscheBahn; - $info =~ s/,Grund//; +my $status = Travel::Status::DE::DeutscheBahn->new( station => shift, ); - while ($route =~ m{$re_via}g) { - if ($first) { - $first = 0; - next; - } - my $stop = $1; - push(@via, $stop); - if ($stop =~ /Hbf$/) { - push(@via_main, $stop); +for my $d ( $status->departures() ) { + + my ( @via, @via_main, @via_show ); + + @via = $d->route; + + for my $stop (@via) { + if ( $stop =~ m{ ?Hbf} ) { + push( @via_main, $stop ); } } pop(@via); - if (@via_main and @via and $via[0] eq $via_main[0]) { + if ( @via_main and @via and $via[0] eq $via_main[0] ) { shift(@via_main); } - if (@via < 3) { + if ( @via < 3 ) { @via_show = @via; } else { - @via_show = splice(@via, 0, (@via_main > 2 ? 1 : 3 - @via_main)); + @via_show = splice( @via, 0, ( @via_main > 2 ? 1 : 3 - @via_main ) ); - while (@via_show < 3 and @via_main) { + while ( @via_show < 3 and @via_main ) { my $stop = shift(@via_main); - if ($stop ~~ \@via_show) { + if ( $stop ~~ \@via_show or $stop eq $d->destination ) { next; } - push(@via_show, $stop); + push( @via_show, $stop ); } } - + for my $stop (@via_show) { + $stop =~ s{ ?Hbf}{}; + } printf( "%5s %-10s %-80s %-20s %-2d %s\n", - $time, - $train, - join(' ', @via_show), - $dest, - $platform, - $info, + $d->time, $d->train, join( q{ }, @via_show ), + $d->destination, $d->platform, $d->info ); - } __END__ @@ -133,6 +58,10 @@ __END__ =head1 SYNOPSIS +=head1 VERSION + +version 0.0 + =head1 DESCRIPTION =head1 OPTIONS @@ -151,4 +80,4 @@ Copyright (C) 2010 by Daniel Friesel Ederf@finalrewind.orgE =head1 LICENSE - 0. You just DO WHAT THE FUCK YOU WANT TO. +This program is licensed under the same terms as Perl itself. diff --git a/lib/Travel/Status/DE/DeutscheBahn.pm b/lib/Travel/Status/DE/DeutscheBahn.pm new file mode 100644 index 0000000..499f540 --- /dev/null +++ b/lib/Travel/Status/DE/DeutscheBahn.pm @@ -0,0 +1,170 @@ +package Travel::Status::DE::DeutscheBahn; + +use strict; +use warnings; +use 5.010; + +use Carp qw(confess); +use LWP::UserAgent; +use POSIX qw(strftime); +use Travel::Status::DE::DeutscheBahn::Departure; +use XML::LibXML; + +our $VERSION = '0.0'; + +sub new { + my ( $obj, %conf ) = @_; + my $date = strftime( '%d.%m.%Y', localtime(time) ); + my $time = strftime( '%H:%M', localtime(time) ); + + my $ua = LWP::UserAgent->new(); + + if ( not $conf{station} ) { + confess('You need to specify a station'); + } + + my $ref = { + post => { + input => $conf{station}, + inputRef => q{#}, + date => $conf{date} || $date, + time => $conf{time} || $time, + productsFilter => '1111101000000000', + REQTrain_name => q{}, + maxJourneys => 20, + delayedJourney => undef, + start => 'Suchen', + boardType => 'Abfahrt', + ao => 'yes', + }, + }; + + $ref->{html} + = $ua->post( 'http://mobile.bahn.de/bin/mobil/bhftafel.exe/dn?rt=1', + $ref->{post} )->content(); + + $ref->{tree} = XML::LibXML->load_html( + string => $ref->{html}, + recover => 2, + suppress_errors => 1, + suppress_warnings => 1, + ); + + return bless( $ref, $obj ); +} + +sub departures { + my ($self) = @_; + + my $xp_element = XML::LibXML::XPathExpression->new( + '//table[@class="result stboard dep"]/tr'); + my $xp_time = XML::LibXML::XPathExpression->new('./td[@class="time"]'); + my $xp_train = XML::LibXML::XPathExpression->new('./td[@class="train"]'); + my $xp_route = XML::LibXML::XPathExpression->new('./td[@class="route"]'); + my $xp_dest = XML::LibXML::XPathExpression->new('./td[@class="route"]//a'); + my $xp_platform + = XML::LibXML::XPathExpression->new('./td[@class="platform"]'); + my $xp_info = XML::LibXML::XPathExpression->new('./td[@class="ris"]'); + + my $re_via = qr{ + ^ \s* (.+?) \s* \n + \d{1,2}:\d{1,2} + }mx; + + for my $tr ( @{ $self->{tree}->findnodes($xp_element) } ) { + + my ($n_time) = $tr->findnodes($xp_time); + my ( undef, $n_train ) = $tr->findnodes($xp_train); + my ($n_route) = $tr->findnodes($xp_route); + my ($n_dest) = $tr->findnodes($xp_dest); + my ($n_platform) = $tr->findnodes($xp_platform); + my ($n_info) = $tr->findnodes($xp_info); + my $first = 1; + + if ( not( $n_time and $n_dest ) ) { + next; + } + + my $time = $n_time->textContent(); + my $train = $n_train->textContent(); + my $route = $n_route->textContent(); + my $dest = $n_dest->textContent(); + my $platform = $n_platform->textContent(); + my $info = $n_info->textContent(); + my @via; + + for my $str ( $time, $train, $dest, $platform, $info ) { + $str =~ s/\n//mg; + $str =~ tr/ //s; + } + + $info =~ s/,Grund//; + + while ( $route =~ m{$re_via}g ) { + if ($first) { + $first = 0; + next; + } + my $stop = $1; + push( @via, $stop ); + } + + push( + @{ $self->{departures} }, + Travel::Status::DE::DeutscheBahn::Departure->new( + time => $time, + train => $train, + route_raw => $route, + route => \@via, + destination => $dest, + platform => $platform, + info => $info, + ) + ); + } + + return @{ $self->{departures} }; +} + +1; + +__END__ + +=head1 NAME + +Travel::Status::DE::DeutscheBahn - Interface to the DeutscheBahn online +departure monitor + +=head1 SYNOPSIS + +=head1 VERSION + +version 0.0 + +=head1 DESCRIPTION + +=head1 METHODS + +=over + +=back + +=head1 DIAGNOSTICS + +=head1 DEPENDENCIES + +=over + +=back + +=head1 BUGS AND LIMITATIONS + +=head1 SEE ALSO + +=head1 AUTHOR + +Copyright (C) 2011 by Daniel Friesel Ederf@finalrewind.orgE + +=head1 LICENSE + +This module is licensed under the same terms as Perl itself. diff --git a/lib/Travel/Status/DE/DeutscheBahn/Departure.pm b/lib/Travel/Status/DE/DeutscheBahn/Departure.pm new file mode 100644 index 0000000..9ca1aa9 --- /dev/null +++ b/lib/Travel/Status/DE/DeutscheBahn/Departure.pm @@ -0,0 +1,69 @@ +package Travel::Status::DE::DeutscheBahn::Departure; + +use strict; +use warnings; +use 5.010; + +use parent 'Class::Accessor'; + +our $VERSION = '0.0'; + +Travel::Status::DE::DeutscheBahn::Departure->mk_ro_accessors( + qw(time train destination platform info)); + +sub new { + my ( $obj, %conf ) = @_; + + my $ref = \%conf; + + return bless( $ref, $obj ); +} + +sub route { + my ($self) = @_; + + return @{ $self->{route} }; +} + +1; + +__END__ + +=head1 NAME + +Travel::Status::DE::DeutscheBahn::Departure - Information about a single +departure received by Travel::Status::DE::DeutscheBahn + +=head1 SYNOPSIS + +=head1 VERSION + +version + +=head1 DESCRIPTION + +=head1 METHODS + +=over + +=back + +=head1 DIAGNOSTICS + +=head1 DEPENDENCIES + +=over + +=back + +=head1 BUGS AND LIMITATIONS + +=head1 SEE ALSO + +=head1 AUTHOR + +Copyright (C) 2011 by Daniel Friesel Ederf@finalrewind.orgE + +=head1 LICENSE + +This module is licensed under the same terms as Perl itself. diff --git a/lib/Travel/Status/DeutscheBahn.pm b/lib/Travel/Status/DeutscheBahn.pm deleted file mode 100644 index dfa50d0..0000000 --- a/lib/Travel/Status/DeutscheBahn.pm +++ /dev/null @@ -1,65 +0,0 @@ -package Travel::Status::DeutscheBahn; - -use strict; -use warnings; -use 5.010; -use base 'Exporter'; - -use LWP::UserAgent; -use XML::LibXML; - -our @EXPORT_OK = (); -my $VERSION = '0.0'; - -sub new { - my ($obj, %conf) = @_; - my $ref = {}; - - my @now = localtime(time()); - - $ref->{post} = { - date => $conf{date} - // sprintf('%d.%d.%d', $now[3], $now[4] + 1, $now[5] + 1900), - time => $conf{time} - // sprintf('%d:%d', $now[2], $now[1]), - input => $conf{station}, - inputef => q{#}, - produtsFilter => '1111101000000000', - REQTrin_name => q{}, - maxJorneys => 20, - delayedJourney => undef, - start => 'Suchen', - boardType => 'Abfahrt', - ao => 'yes', - }; - - return bless($ref, $obj); -} - -sub get { - my ($self) = @_; - my $ua = LWP::UserAgent->new(); - my $reply = $ua->post( - 'http://mobile.bahn.de/bin/mobil/bhftafel.exe/dox', - $self->{post}, - )->content(); - my $tree = XML::LibXML->load_html( - string => $reply, - recover => 2, - suppress_errors => 1, - suppress_warnings => 1, - ); - - my $xp_element - = XML::LibXML::XPathExpression->new('//div[@class="sqdetailsDep trow"]'); - my $xp_line = XML::LibXML::XPathExpression->new('./a/span'); - my $xp_dep = XML::LibXML::XPathExpression->new('./span[1]'); - - for my $div (@{$tree->findnodes($xp_element)}) { - say $div->findnodes($xp_line)->[0]->textContent(); - say $div->findnodes($xp_dep)->[0]->textContent(); - say q{}; - } -} - -1; -- cgit v1.2.3