LWP::Simple(捉取整个html文件简易模块,与 wget 类似)
如果只是要拿到某个网页,那使用LWP::Simple里的函数是最简单的。通过调用get($url)函数,就可以得到相关网址的内容。
#$content里是网页内容,下面是对此内容作些分析:
非常简单易懂。拿网页内容是容易的,难的是用正则过滤需要的内容。
HTML::TreeBuilder
这个解析模块使用了强大的 HTML::Element 模块。解析时,HTML::TreeBuilder模块把整个 html 文档转换成了 perl 的数据结构,可以进行任意的操作。
使用时先创建一个 HTML::TreeBuilder 对象。
use Data::Dumper qw(Dumper);
$Data::Dumper::Indent = 1;
use HTML::TreeBuilder;
my $tree = new HTML::TreeBuilder;
直接向 HTML::TreeBuilder 传递文件好像会把中文转换成 unicode 的字符,所以一般传递文件句柄。而且传递的字符串或者句柄一般要先确保是 utf8 字符串才行,不然会有一个warning:
Parsing of undecoded UTF-8 will give garbage when decoding entities at /home/ywb/temp/t.pl line 16, <DATA> line 5.
解析文件和解析字符串的区别仅仅是前者是使用 parse_file 函数,而后者使用parse 函数。下面以解析文件句柄的例子:
binmode DATA, "utf8";
$tree->parse_file(\*DATA);
print Dumper($tree), "\n";
__DATA__
<table border="1" cellspacing="0" cellpadding="6">
</table>
要提取出表格中的内容可以这样:
foreach my $row ( $tree->find_by_tag_name("tr") ) {
}
由于 HTML::Element 会强制把所有的 tag 都转换成小写,所以不用担心 tag的大小写问题。
HTML::TokenParser
HTML::TokenParser和 HTML::Parser 等模块不同,HTML::TokenParser 模块是类似于流(stream oftokens)的方式来解析 HTML 文件。在解析的过程中 HTML 中的文本转换成这六种token:
这个例子应该能够体现这个模块解析的一些特点:
use HTML::TokeParser;
my $file = \*DATA;
my $parser = HTML::TokeParser->new($file)
my (@table, @row, $inrow);
while (my $token = $parser->get_token( )) {
}
print Dumper(\@table), "\n";
__DATA__
<table border="1" cellspacing="0" cellpadding="6">
</table>
与前面 HTML::TreeBuilder 的例子相比可能有些麻烦,但是很多情况下,只需要一次处理一个 token,这时候用这个模块就非常方便了,比如你要得到一个html 里所有的图片或者所有的链接,像这样写就行了:
my @images;
while (my $token = $parser->get_token( )) {
}
__DATA__
<img src="/perl6.jpg" alt="Steroidal Camel">
HTML::LinkExtor
专门的模块HTML::LinkExtor如果要提取 html 文件中的链接,也不用自己写了,用 HTML::LinkExtor 就好了。一个简单的例子:
require HTML::LinkExtor;
my $p = HTML::LinkExtor->new();
$p->parse_file(\*DATA);
print Dumper($p->links), "\n";
__DATA__
<a href="xlink">x</a>
<img src="/perl6.jpg" alt="Steroidal Camel">
HTML::LinkExtor 的 new 函数可以提供一个 callback 函数,这个函数是当发现链接时就调用这个函数。传递给这个函数的第一个参数是链接的类型,比如 'a','img',其余的参数是链接的属性。如果提供了 callback 函数,HTML::LinkExtor 就不再累积链接了,这意味着你不能再用 links 函数来得到所有的链接。要得到所有链接,只有在 callback 函数里自己保存好。
require HTML::LinkExtor;
my $p = HTML::LinkExtor->new(\&cb);
$p->parse_file(\*DATA);
sub cb {
}
__DATA__
<a href="xlink">x</a>
<img src="/perl6.jpg" alt="Steroidal Camel">
HTML::HeadParser
如果只是要得到 html 的标题或者其它在 head 标签之间内容,就不要用HTML::TreeBuilder 这样的重量级模块了,HTML::HeadParser 模块就能完成这个任务,并且使用相当简单。
require HTML::HeadParser;
my $p = HTML::HeadParser->new;
my $text = join('', <DATA>);
$p->parse($text) and
# to access <title>....</title>
print "Title: ", $p->header('Title'), "\n";
# to access <base href="http://...">
print "Base:
# to access <meta http-equiv="Foo" c>
print "Content type:", $p->header('Content-Type'), "\n";
# to access <meta name="Foo" c>
print "Author:", $p->header('X-Meta-Author'), "\n";
print Dumper($p->header), "\n";
__DATA__
<head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<meta name="generator" content="Org-mode"/>
<meta name="author" content="Ye Wenbin"/>
<style type="text/css">
</style>
<script language='JavaScript' src='/js/iceajax.js' TYPE='text/javascript'></script>
<link rel=stylesheet href="core.css" type="text/css">
</head>
可以看出它不能解析出 script、link、style 这样的标签。
HTML::TableExtract
HTML::TableExtract 只能从 html 中提取出 table 里的内容。如果只要这个,那么这个模块是很容易使用的。
use HTML::TableExtract;
use Data::Dumper qw(Dumper);
my $html_string = join("", <DATA>);
$te = HTML::TableExtract->new();
$te->parse($html_string);
print Dumper($te), "\n";
foreach $ts ($te->tables) {
}
__DATA__
<table border="1" cellspacing="0" cellpadding="6">
</table>
由这个例子可以看出,解析后链接信息都丢失了。但是表格里的内容是很容易得到的。