анализировать RSS-канал с помощью PERL с использованием XML: LibXML - PullRequest
0 голосов
/ 15 сентября 2011

К сожалению, мне нужно проанализировать RSS-канал, поскольку другого способа получения данных нет.У меня есть сценарий Perl, который работал раньше, чтобы проанализировать файл XML.Я подумал, что могу изменить его, чтобы сделать то же самое для RSS-канала, чтобы я мог получить данные в формате, который легче использоватьИмея это в виду, я изменил свой файл.Но на самом деле кажется, что он не находит никаких данных из канала.Вот ядро ​​кода.

foreach my $channel ($root->findnodes('channel')) {
  foreach my $item ($root->findnodes('item')) {
    my $guid = $item->findvalue('guid');
    my $title = $item->findvalue('title');
    my $link = $item->findvalue('link');
    my $description = $item->findvalue('description');
    my $pubdate = $item->findvalue('pubdate');
    print DATA "INSERT INTO events VALUES ( \"$guid\", \"$title\", \"$link\",\"$description\", \"$pubdate\" ); \n";
  }
}

Есть идеи?

1 Ответ

4 голосов
/ 16 сентября 2011

Отложив на мгновение отличное предложение от Ричарда Симойса , чтобы использовать XML :: RSS ...

Я думаю, что основная проблема, с которой вы сталкиваетесь, связана с пространствами имен XML. Рассмотрим следующую строку вашего скрипта:

$root->findnodes('channel')

Он ищет элемент типа 'channel' , но ваш исходный документ, вероятно, не содержит такого элемента. То, что вы должны искать, это что-то вроде: элемент типа 'channel' в пространстве имен, идентифицируемый URI 'http://purl.org/rss/1.0/'.

Работать с пространствами имен нелегко. Существует два типа: пространство имен по умолчанию (например: xmlns = "http://purl.org/rss/1.0/"); и пространства имен, объявленные с префиксом (например: xmlns: rss =" http://purl.org/rss/1.0/"). В любом случае единственное, что имеет значение, это URI пространства имен. Префикс объявленный в документе (например, 'rss:') не имеет отношения к вашему сценарию.

Чтобы использовать пространства имен с libxml, вам нужно объявить свой собственный префикс для каждого URI пространства имен, а затем использовать этот префикс в своих вызовах для findnodes. Вы можете выбрать префикс, который совпадает с префиксом в документе или отличается - он не имеет значения, если URI одинаков. Вам необходимо использовать объект XML :: LibXML :: XPathContext, чтобы связать URI пространства имен с префиксами, а затем направить запросы через этот объект контекста.

Это версия вашего скрипта, которая, вероятно, ближе к тому, что вы хотите.

#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;
use XML::LibXML::XPathContext;

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file('slashdot.rss');
my $root   = $doc->documentElement();

my $xc     = XML::LibXML::XPathContext->new( $root );
$xc->registerNs( rss => 'http://purl.org/rss/1.0/' );

foreach my $channel ($xc->findnodes('rss:channel')) {
    foreach my $item ($xc->findnodes('rss:item')) {
        my $guid = $xc->findvalue('rss:guid', $item);
        my $title = $xc->findvalue('rss:title', $item);
        my $link = $xc->findvalue('rss:link', $item);
        my $description = $xc->findvalue('rss:description', $item);
        my $pubdate = $xc->findvalue('rss:pubDate', $item);
        print "INSERT INTO events VALUES ( \"$guid\", \"$title\", \"$link\",\"$description\", \"$pubdate\" ); \n";
    }
}

В документе, который вы пытаетесь проанализировать, возможно, используется другая версия RSS и, следовательно, другой URI пространства имен RSS - это лишь одна из многих причин использовать модуль RSS, а не пытаться делать это вручную.

Как указывало ikegami , интерполяция значений в SQL - плохая идея. В вашем примере вы генерируете SQL со строковыми литералами в двойных кавычках (вы, вероятно, хотели использовать одинарные кавычки). Это не удастся, если любое из значений, извлеченных из RSS, содержит символ двойной кавычки. Одиночные и двойные кавычки очень часто встречаются в RSS.

...