[Bielefeld-pm] RSS parsen
Nils Diewald
nils at diewald-online.de
Mi Mär 30 08:28:11 PDT 2011
Oh - Perlanet kannte ich noch nicht. Wobei das schon sehr nach einer
All-in-One-Lösung ausschaut, die vielleicht nicht unbedingt zum
Reader-Building geeignet ist (aber OPML unterstützt - das ist schon nett).
Neben RSS sollte ja auch ATOM unterstützt werden, das macht das Parsing
noch etwas komplexer, wobei die RSS-Varianten sich gar nicht so arg
unterscheiden (es gibt nur zwei oder drei nennenswert verschiedene
Versionen).
Ich habe ein Script angefügt, das ich für RSS mal geschrieben hatte
(allerdings etwas anders einsetzte).
Die Google-Reader-Alternative, von der ich gestern sprach, ist übrigens
Newsblur: http://www.newsblur.com/
Es ist auch OS, aber kommerziell: https://github.com/samuelclay/NewsBlur
Viele Grüße,
Nils
Am 30.03.2011 16:20, schrieb Renée Bäcker:
> Ich setze für planet.perl-magazin.de das Modul Perlanet [1] ein. Das ist
> sehr einfach einzurichten!
>
> http://search.cpan.org/dist/Perlanet/
>
>
> On 30.03.2011 15:49, taulmarill at xgn.de wrote:
>> Hallo zusammen,
>>
>> nachdem sich gestern der Bedarf nach einer OS Alternative zu Google Reader
>> herauskristallisiert hat, möchte ich zuerst mal an den größeren Kreis der
>> Personen die hier mitlesen noch mal die Frage stellen, ob so etwas
>> irgendwo bekannt ist.
>> Für den Fall dass es doch nicht anders geht, als selber was zu bauen, habe
>> ich mich mit dem Thema schon einmal flüchtig beschäftigt. Das größte
>> Problem dürften die vielen, verschiedenen Versionen sein (alleine neun
>> RSS-Versionen, bei Atom habe ich noch nicht geschaut). Allerdings lässt
>> sich das mit Mojo::DOM ganz gut abfrühstücken, hier mal ein minimales
>> Beispiel:
>>
>> -----<start>-----
>> use strict;
>> use warnings;
>>
>> use Mojo::UserAgent;
>>
>> my $ua = Mojo::UserAgent->new;
>>
>> my $feed = $ua->get('http://www.heise.de/ix/news/news.rdf')->res->dom;
>>
>> if ( my $title = $feed->at('channel title') ) {
>> print $title->text . "\n";
>> }
>>
>> if ( my $description = $feed->at('channel description') ) {
>> print $description->text . "\n";
>> }
>>
>> if ( my $items = $feed->find('item title') ) {
>> $items->each(sub {print "=> " . shift->text . "\n"});
>> }
>> -----<end>-----
>>
>> Da sollte sich eigentlich was basteln lassen...
>>
>>
>> Gruß,
>> Jürgen
>>
>> _______________________________________________
>> Bielefeld-pm mailing list
>> Bielefeld-pm at pm.org
>> http://mail.pm.org/mailman/listinfo/bielefeld-pm
>>
>>
>>
>
-------------- nächster Teil --------------
#!/usr/bin/perl
use strict;
use warnings;
use Mojolicious::Lite;
app->secret('jgfhfztrezhf5rvb brvbg');
get '/test' => sub {
shift->render('template' => 'test')
};
get '/' => sub {
my $self = shift;
my $c = $self->ua;
$c->max_redirects(3);
my $xml = $c->get('http://netzwertig.com/feed/')->res->dom;
# TODO: Paths can be relative or without the correct base!
# http://cyber.law.harvard.edu/rss/rss.html
my ($title, $channel_date);
if ($title = $xml->at('channel title')) {
$title = $title->text;
};
if ($channel_date = $xml->at('channel pubdate')) {
$channel_date = $channel_date->text;
};
my @array;
$xml->find('item')->each(sub {
my %item;
$item{'title'} = $_->at('title') ? $_->at('title')->text : '';
$item{'creator'} = $_->at('creator') ? $_->at('creator')->text : '';
$item{'link'} = $_->at('link') ? $_->at('link')->text : '';
$item{'pubDate'} = $_->at('pubdate') ? $_->at('pubdate')->text : '';
# content namespace!
my $content = '';
my $content_ns = 'http://purl.org/rss/1.0/modules/content/';
if (($content = $_->at('encoded')) && ($content->namespace eq $content_ns)) {
$item{'content'} = clean_content($content->text);
} elsif ($content eq $_->at('description')) {
$item{'content'} = clean_content($content->text);
};
my $image;
# <enclosure type="image/jpeg" url="http://www.spiegel.de/images/image-146217-thumbsmall-nztv.jpg"/>
if ($image = $_->at('enclosure[type^="image"]')) {
$item{'image'} = $image->attrs->{'url'} || '';
} else {
$item{'image'} = undef;
};
push(@array, \%item);
});
$self->render(
template => 'index',
title => $title,
channel_date => $channel_date,
items => \@array);
};
sub clean_content {
my $string = shift;
if ($string =~ /[<>]/) {
my $INSECURE_ATTRNAME_RE =
qr/(?i:id|class|style|on(?:blur|change|(?:dbl)?click|error|
focus|key(?:down|press|up)|mouse(?:down|move|out|over|up)|
resize|select|unload))/x;
# (?:[^:]+:[^:]+)
my $INSECURE_ATTR_RE = qr/$INSECURE_ATTRNAME_RE\s*=\s*(?:"([^"]*)"|'([^']*)')/;
$string =~ s/\s*$INSECURE_ATTR_RE\s*//g;
$string =~ s/(href)\s*=\s*("([^"]*)"|'([^']*)')/href=$2/gi;
my $content = Mojo::DOM->new->parse($string);
$content->find('script')->each(
sub { shift->replace('') }
);
$content->find('a')->each(
sub {
my $a = shift;
my $href = $a->attrs->{'href'};
if ($href =~ /^\s*javascript:/i) {
$a->replace($a->inner_xml);
};
}
);
return $content->to_xml;
} else {
return $string;
};
};
app->start;
__DATA__
@@ layouts/standard.html.ep
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head><title><%= title %></title></head>
<body>
<%= content %>
</body>
</html>
@@ index.html.ep
% layout 'standard';
<h1><%= title %></h1>
<p><%= $channel_date %></p>
% foreach (@$items) {
<div style="background-color: #efe; border: 2px solid #898; margin: 2em; padding: 2em;">
<% if ($_->{image}) { %><img src="<%= $_->{image} %>" alt="<%= $_->{title} %>" style="float: right;" /><% } %>
<h3><a href="<%= $_->{link} %>"><%= $_->{title} %></a></h3>
<p style="padding-left: 3em; color: grey;">von <%= $_->{creator} %> am <%= $_->{pubDate} %></p>
<% if ($_->{'content'}) { %>
<%== $_->{'content'} %>
<% } %>
</div>
% }
Mehr Informationen über die Mailingliste Bielefeld-pm