[Perl Module] HTML::TreeBuilder::XPath 来解析网页内容

Sep 24th, 2009

转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]

本文链接: http://www.php-oa.com/2009/09/24/perl-html-tree-builder-xpath.html

强大的Perl中,有超级多强大的模块,让我们不在需要重复的发明轮子.下面这个就是一个强大的模块.HTML::TreeBuilder::XPath.它能象xml一样解析网站.怎么使用就不细讲了,如下,见实例,我是从alexa.com网站得到我的网站排名的一个例子.会显示如下的结果

$ perl  test.pl
你的网站排名为: 199,954

HTML::TreeBuilder::XPath的实例

#!/usr/bin/perl
use strict;

use LWP::Simple;
use HTML::TreeBuilder::XPath;
use Data::Dumper;

my $url = "http://www.alexa.com/siteinfo/www.php-oa.com";
my $html = get( $url );
my $tree = new HTML::TreeBuilder::XPath;
$tree->parse( $html );
$tree->eof;
#$tree->dump;
my $srt;
my $items = $tree->findnodes( '/html/body/descendant::div[@class[.=~/data down/]]' );
for my $item ( $items->get_nodelist() ){
        eval{
            $srt  = $item->content->[1];
        };
        print "你的网站排名为:".$srt."\n";
    }

怎么使用最麻烦的一点在于这个XPath的语法.下面是简单的语法介绍.


下面列出了最有用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点.
/ 从根节点选取.
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置.
. 选取当前节点.
.. 选取当前节点的父节点.
@ 选取属性.

 

实例

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点.
/bookstore

选取根元素 bookstore.

注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

bookstore/book 选取属于 bookstore 的子元素的所有 book 元素.
//book 选取所有 book 子元素,而不管它们在文档中的位置.
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置.
//@lang 选取名为 lang 的所有属性.

 

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点.

谓语被嵌在方括号中.

实例

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素.
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素.
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素.
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素.
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素.
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性.
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00.
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00.

选取未知节点

XPath 通配符可用来选取未知的 XML 元素.

通配符 描述
* 匹配任何元素节点.
@* 匹配任何属性节点.
node() 匹配任何类型的节点.

实例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素.
//* 选取文档中的所有元素.
//title[@*] 选取所有带有属性的 title 元素.

选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径.

实例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素.
//title | //price 选取文档中的所有 title 和 price 元素.
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素.

XPATH的简单语法介绍

XPATH基本上是用一种类似目录树的方法来描述在XML文档中的路径.比如用“/”来作为上下层级间的分隔.第一个“/”表示文档的根节点(注意,不是指文档最外层的tag节点,而是指文档本身).比如对于一个HTML文件来说,最外层的节点应该是"/html".

同样的,“..”和“.”分别被用来表示父节点和本节点.

XPATH返回的不一定就是唯一的节点,而是符合条件的所有节点.比如在HTML文档里使用“/html/head/scrpt”就会把head里的所有script节点都取出来.

为了缩小定位范围,往往还需要增加过滤条件.过滤的方法就是用“[”“]”把过滤条件加上.比如在HTML文档里使用“/html/body/div[@id='main']”,即可取出body里id为main的div节点.

其中@id表示属性id,类似的还可以使用如@name, @value, @href, @src, @class….

而函数text()的意思则是取得节点包含的文本.比如:<div>hello<p>world</p>< /div>中,用"div[text()='hello']"即可取得这个div,而world则是p的text().

函数position()的意思是取得节点的位置.比如“li[position()=2]”表示取得第二个li节点,它也可以被省略为“li[2]”.

不过要注意的是数字定位和过滤条件的顺序.比如“ul/li[5][@name='hello']”表示取ul下第五项li,并且其name必须是hello,否则返回空.而如果用 “ul/li[@name='hello'][5]”的意思就不同,它表示寻找ul下第五个name为"hello“的li节点.

此外,“*”可以代替所有的节点名,比如用"/html/body/*/span"可以取出body下第二级的所有span,而不管它上一级是div还是p或是其它什么东东.

而 “descendant::”前缀可以指代任意多层的中间节点,它也可以被省略成一个“/”.比如在整个HTML文档中查找id为“leftmenu”的 div,可以用“/descendant::div[@id='leftmenu']”,也可以简单地使用“ //div[@id='leftmenu']”.

至于“following-sibling::”前缀就如其名所说,表示同一层的下一个节点."following-sibling::*"就是任意下一个节点,而“following-sibling::ul”就是下一个ul节点.

备注: 是我发现这个的最好的实现

 

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪 ViVi 365Key 网摘 天极网摘 和讯网摘 博拉网 POCO 网摘 饭否 QQ 书签 Digbuzz 我挖网 Mister Wong