webForumDet fria alternativet

Hämta information från svt.

7 svar · 595 visningar · startad av Myten

MytenMedlem sedan okt. 200313 inlägg
#1

Jag pillar med ett script som hämtar info från http://www.svt.se/texttv/650.html (dvs, "just nu på tv") med LWP::Simple.

Jag får ner sidan och allt, men nu vill jag få ut vissa värden.
Så om någon vänlig regexpare skulle vilja ta tag i följande textsnutt vore det helfett:

<FONT COLOR="#6f6f6f"> 00.45-01.15</FONT><FONT COLOR="#007f00"> 24 Nöje </FONT><FONT COLOR="#6f6f6f"> 24 </FONT>

Det är 00.45-01.15, 24 Nöje och 24 jag vill åt (just i detta exemplet givetvis.)

Jag testade själv med följande regexp, men det vill inte fungera:
<FONT COLOR="#6f6f6f">\s+\d+</FONT><FONT COLOR="#007f00">\s+(.+)\s+</FONT><FONT COLOR="6f6f6f">\s+(.+)\s*</FONT>

JoakimMedlem sedan dec. 199982 inlägg
#2
<.*> (\d\d\.\d\d-\d\d\.\d\d)<.*><.*> (.*) <.*><.*> (.*) <.*>

Borde nog fungera? Går säkert att göra både bättre och snyggare men jag är så seg så det får duga =)

Tänk på att det är lagbrott att publicera deras tablå på en hemsida, enstaka program faller dock under klassificeringen citat.

När man pillar med regexp är följande program guld värt:
http://weitz.de/regex-coach/
Där skriver du in strängen du skall matcha mot och ditt regexp så kan du direkt se hur det hela funkar och vad som matchas. Klockrent.

MytenMedlem sedan okt. 200313 inlägg
#3

Jag ska testa det, tackar!

Jag skall inte publicera det på någon hemsida, jag ska bara använda det vid min terminal ;)

MytenMedlem sedan okt. 200313 inlägg
#4

Det fungerade bra, förutom när vissa rader innehåller länkar till typ beskrivningar av programmen.

T.ex. <FONT COLOR="#6f6f6f"> 22.00-23.55</FONT><FONT COLOR="#007f00"> Gilbert Grape</FONT><FONT COLOR="#8f8f15"> <a href=637.html>637</a> </FONT><FONT COLOR="#6f6f6f"> SVT2 </FONT>

HansenMedlem sedan aug. 2000374 inlägg
#5

Jag hade tacklat problemet på ett annat sätt:

#!/usr/bin/perl

use strict;
use warnings;

use LWP::UserAgent;

my $agent    = LWP::UserAgent->new;
my $response = $agent->get('http://www.svt.se/texttv/650.html');

unless ( $response->is_success ) {
    die( $response->status_line );
}

my $html    = $response->content;
my $fonts   = [];
my $entries = [];
my $begin   = 0;

while ( $html =~ m{<font color="(#6f6f6f|#007f00)">(.*?)</font>}igs ) {

    my ( $color, $text ) = ( $1, $2 );

    $text =~ s/^\s+//;
    $text =~ s/\s+$//;
    
    if ( $begin ) {
    
       if ( $text =~ m/Kommande program/ ) {
          last;
       }
       
       push @$fonts, { color => $color, text => $text };
    }
    else {
    
       if ( $text =~ m/P.g.ende program/ ) {
          $begin = 1;
       }
       
       next;
    }
}

for ( my $i = 0 ; $i < scalar(@$fonts) ; $i += 3 ) {

    my $entry = {};

    $entry->{duration} = $fonts->[ $i     ]->{text};
    $entry->{show}     = $fonts->[ $i + 1 ]->{text};
    $entry->{channel}  = $fonts->[ $i + 2 ]->{text};

    if ( defined $fonts->[ $i + 3 ]
        and $fonts->[ $i + 3 ]->{color} eq '#007f00' )
    {
        $entry->{show} .= " " . $fonts->[ $i + 3 ]->{text};
        $i++;
    }

    push @$entries, $entry;
}

binmode( STDOUT, ':utf8' );

while ( my $entry = shift(@$entries) ) {
    printf( "%s %-30s %s\n", $entry->{duration},
                             $entry->{show},
                             $entry->{channel} );
}

output:

mundus:~/dev/perl/svt chansen$ ./ontv 
14.30-16.00 Kvinna ombord                  SVT1
12.00-15.10 Riksdagen i dag                SVT2
12.15-15.15 Partiledardebatt i...          24
12.00-15.00 Twebbys smågodis               Barn
14.30-15.00 Galen i dig                    TV3
14.35-15.00 Glamour                        TV4
14.35-15.05 Ett hem i...                   Kanal 5
MytenMedlem sedan okt. 200313 inlägg
#6

Jag förstår inte hur du har gjort, men du ska ha creds som fixade det :)

Jag ska ändock försöka klura ut en egen lösning. Just nu försöker jag lite med HTML::TokeParser.

HansenMedlem sedan aug. 2000374 inlägg
#7

Myten skrev:

Jag förstår inte hur du har gjort, men du ska ha creds som fixade det :)

Vad är det du inte förstår, om du kan precisera det lite så kan jag nog hjälpa dig :)

Myten skrev:

Jag ska ändock försöka klura ut en egen lösning. Just nu försöker jag lite med HTML::TokeParser.

Perl Monks har en tutorial om HTML::TokeParser.

CPAN har många moduler för att göra livet lättare, en av mina favoriter för att "skrapa" html är XML::LibXML.

Med XML::LibXML kan du använda DOM och XPATH för att "skrapa" html koden, här är ett exempel som hämtar "På TV Just nu" från DagensTv.com.

#!/usr/bin/perl

use strict;
use warnings;

use LWP::UserAgent;
use Text::Wrap;
use XML::LibXML;

my ( $parser, $xpath, $entries );

my $agent    = LWP::UserAgent->new;
my $response = $agent->get('http://www.dagenstv.com/se/chart/?now=1');

unless ( $response->is_success ) {
    die( $response->status_line );
}

$parser = XML::LibXML->new();
$parser->recover(1);

my $doc  = $parser->parse_html_string( $response->content );
my $list = $doc->findnodes('//tr[ child::td[ contains( @class, "charttime") ] ]');

while ( my $node = $list->shift ) {

    my $entry = {};

    # Channel
    $entry->{channel} = $node->findvalue('td[1]/img/@alt');

    # Name
    $xpath = 'descendant::*[ contains( @class, "name") ]/text()';
    $entry->{name} = trim( $node->findvalue($xpath) );

    # Description
    $xpath = 'descendant::*[ contains( @class, "description") ]/text()';
    $entry->{description} = trim( $node->findvalue($xpath) );
    $entry->{description} = wrap( '', '', $entry->{description} );

    # Time begin
    $xpath = 'descendant::*[ contains( @class, "time") ]/text()';
    $entry->{time_begin} = trim( $node->findvalue($xpath) );

    # Time end
    $xpath = 'descendant::*[ contains( @class, "name") ]/following-sibling::text()';
    $entry->{time_end} = ( $node->findvalue($xpath) =~ m/(\d+:\d+)/ )[0];

    push @$entries, $entry;
}

sub trim {
    my $string = shift;
    $string =~ s|^\s+||;
    $string =~ s|\s$||;
    $string =~ s|\s+| |;
    return $string;
}

my @channels = ( 'SVT1', 'SVT2', 'TV3', 'TV4', 'TV4 Plus', 'Kanal 5', 'MTV' );

my %wanted = map { $_ => 1 } @channels;

my $format = <<'END';

%s-%s  %-46s %15s
---------------------------------------------------------------------------
%s

END

binmode( STDOUT, ':utf8' );

while ( my $entry = shift(@$entries) ) {

    unless ( $wanted{ $entry->{channel} } ) {
        next;
    }

    printf( $format, $entry->{time_begin}, 
                     $entry->{time_end}, 
                     $entry->{name},
                     $entry->{channel}, 
                     $entry->{description} );
}
MytenMedlem sedan okt. 200313 inlägg
#8

Vad är det du inte förstår, om du kan precisera det lite så kan jag nog hjälpa dig

Vi har helt enkelt olika sätt att lösa problem, dina funkar till skillnad från mina :P. Sen är jag ganska grön när det kommer till Perl iochförsig. Och vad jag har förstått så _ska_ det vara svårt att förstå andra Perl-script :q.

Perl Monks har en tutorial om HTML::TokeParser.

Jag har varit där inne och läst, men jag har inte lyckats greppa tankegången. Om du har tid och lust kan du ju göra ett exempelprogram så att jag kanske förstår bättre :P.

135 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)