如何使用Perl的LWP从网站提取XML并保存到文件?

3

如何从网站(http://tv.yahoo.com/listings)中提取信息并创建XML文件?我想保存它以便稍后解析,并使用JavaScript显示信息。

我对Perl很陌生,不知道如何实现。

4个回答

11

当然。最简单的方法是使用 Web::Scraper 模块。它允许你定义由以下几个部分组成的抓取器对象:

  1. 哈希键名
  2. XPath 表达式,用于定位感兴趣的元素
  3. 从其中提取数据的代码

抓取器对象接受一个 URL 并返回提取的数据哈希表。如果需要,每个键的提取器代码本身也可以是另一个抓取器对象,这样您就可以定义如何抓取重复的复合页面元素:在外部抓取器中提供查找复合元素的 XPath,然后在内部抓取器中提供一堆更多的 XPath 来提取其各个部分。结果自动成为嵌套的数据结构。

简而言之,您可以非常优雅地将页面上的数据提取到 Perl 数据结构中。在这样做时,XPath + Perl 的全部功能可用于针对任何页面使用。由于页面是使用 HTML::TreeBuilder 解析的,因此无论标签嵌套有多糟糕,都没有关系。生成的抓取器脚本比基于正则表达式的抓取器更易于维护,并且容忍性更强,可以容忍轻微的标记变化。

不好的消息是,目前它的文档几乎不存在,因此您必须通过搜索类似 [miyagawa web::scraper] 这样的内容来查找模块作者发布的示例脚本。


你真的想推荐这种 beta 模块吗? - Account deleted
Beta,真的吗?它是LWP、HTML::TreeBuilder和HTML::Selector::XPath组合的胶水,所有这些都是经过实战检验的生产质量模块。如果你喜欢编写样板代码,那就随便你了... - Aristotle Pagaltzis
我还没有尝试过,所以可能是我过早下结论了。但是作者指出:“此模块处于测试质量阶段。API 是从 Scrapy 中窃取的,但未来可能会更改。” - Account deleted

3

虽然通常使用LWP::SimpleWWW::MechanizeHTML::Tree从网页中提取数据是不错的方法,但在这种特定情况下(电视节目清单),有一种更简单的方法:

使用XMLTVSchedules Direct的数据。虽然有少量费用(每年20美元),但有以下优点:

  1. 解析代码已经为您编写(只需使用use XMLTV;)。
  2. 您不会违反Yahoo的服务条款。
  3. 您将不必处理Yahoo积极试图破坏您的脚本的问题。(他们不喜欢自动化脚本下载电视节目清单,请参见#2。)

1

tv.yahoo.com不是很语义化,也不是很容易爬取!也许有更好的替代方案或者源吗?

使用pQuery,我可以快速获取时间和节目信息...

use pQuery;
pQuery( 'http://tv.yahoo.com/listings' )
    ->find( '.show' )->each(
        sub {
            my $n = shift;
            my $pQ = pQuery( $_ ); 
            say $pQ->text;
        }
    );

  # => 4:00pm - 6:30pm Local Programming

如果想要更详细地抓取信息,可以尝试这个方法...

use pQuery;
my @tv_progs;
pQuery( 'http://tv.yahoo.com/listings' )
    ->find( 'li div strong' )->each(
        sub {
            my $n = shift;
            my $pQ = pQuery( $_ ); 
            $tv_progs[ $n ]->{ time } = $pQ->text;
        }
    )
    ->end
    ->find( '.showTitle' )->each( 
        sub {
            my $n = shift;
            my $pQ = pQuery( $_ ); 
            $tv_progs[ $n ]->{ name } = $pQ->text;
        }
    );

for my $prog ( @tv_progs ) {
    say $prog->{name} . " @ " . $prog->{time};
}

   # => Local Programming @ 4:00pm - 6:30pm

要获取频道....

use pQuery;
pQuery( 'http://tv.yahoo.com/listings' )
->find( '.chhdr a' )->each(
    sub {
        my $n = shift;
        my $pQ = pQuery( $_ ); 
        say $pQ->text;
    }
);

  # => ABC

然而,将回传通道与程序信息匹配需要一些工作;-)


1
如果你想将信息传递给Javascript,使用Javascript对象表示法(JSON)而不是XML。有很多Perl库,比如JSON::Any,可以为你处理这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接