我正在使用TokeParser来提取标签内容.
...
$text = $p->get_text("/td") ;
...
Run Code Online (Sandbox Code Playgroud)
通常它会返回清理的文本.我想要的是返回td和之间的/td所有其他html元素.怎么做.
我正在使用本教程中的示例.谢谢
在这个例子中,
my( $tag, $attr, $attrseq, $rawtxt) = @{ $token };
Run Code Online (Sandbox Code Playgroud)
我相信有一些诀窍$rawtxt.
HTML :: TokeParser没有内置功能来执行此操作.但是,可以通过<td>单独查看s 之间的每个标记来实现.
#!/usr/bin/perl
use strictures;
use HTML::TokeParser;
use 5.012;
# dispatch table with subs to handle the different types of tokens
my %dispatch = (
S => sub { $_[0]->[4] }, # Start tag
E => sub { $_[0]->[2] }, # End tag
T => sub { $_[0]->[1] }, # Text
C => sub { $_[0]->[1] }, # Comment
D => sub { $_[0]->[1] }, # Declaration
PI => sub { $_[0]->[2] }, # Process Instruction
);
# create the parser
my $p = HTML::TokeParser->new( \*DATA ) or die "Can't open: $!";
# fetch all the <td>s
TD: while ( $p->get_tag('td') ) {
# go through all tokens ...
while ( my $token = $p->get_token ) {
# ... but stop at the end of the current <td>
next TD if ( $token->[0] eq 'E' && $token->[1] eq 'td' );
# call the sub corresponding to the current type of token
print $dispatch{$token->[0]}->($token);
}
} continue {
# each time next TD is called, print a newline
print "\n";
}
__DATA__
<html><body><table>
<tr>
<td><strong>foo</strong></td>
<td><em>bar</em></td>
<td><font size="10"><font color="#FF0000">frobnication</font></font>
<p>Lorem ipsum dolor set amet fooofooo foo.</p></td>
</tr></table></body></html>
Run Code Online (Sandbox Code Playgroud)
该程序将解析该__DATA__部分中的HTML文档,并在<td>和之间打印包括HTML在内的所有内容</td>.它将打印一行<td>.让我们一步一步地完成它.
阅读完文档后,我了解到HTML :: TokeParser中的每个标记都有一个与之关联的类型.有六种类型:S,E,T,C,D和PI.医生说:
此方法将返回HTML文档中找到的下一个标记,或文档末尾的undef.令牌作为数组引用返回.数组的第一个元素是一个字符串,表示该标记的类型:"S"表示开始标记,"E"表示结束标记,"T"表示文本,"C"表示注释,"D"表示声明,以及"PI"表示流程说明.令牌数组的其余部分取决于这样的类型:
Run Code Online (Sandbox Code Playgroud)["S", $tag, $attr, $attrseq, $text] ["E", $tag, $text] ["T", $text, $is_data] ["C", $text] ["D", $text] ["PI", $token0, $text]
我们想要访问$text存储在这些令牌中的内容,因为没有其他方法可以获取看起来像HTML标记的内容.因此,我创建了一个调度表来处理它们%dispatch.它存储了一堆稍后调用的代码引用.
__DATA__,这对于这个例子很方便.<td>使用该get_tag方法获取s .@ nrathaus的评论指出了我的方式.它将在打开后将解析器移动到下一个标记<td>.我们不关心什么get_tag返回,因为我们只想要后面的令牌<td>.我们使用该方法get_token获取下一个令牌并使用它执行操作:
</td>.如果我们看到,我们标记next了外部while循环TD.continue块被调用并打印换行符.如果我们不在最后,魔术就会发生:调度表; 正如我们之前看到的,令牌数组ref中的第一个元素保存了类型.每个类型都有一个代码ref %dispatch.我们称它为并通过完整的数组引用$token通过去$coderef->(@args).我们在当前行上打印结果.
这将产生这样的东西<strong>,foo,</strong>等在每次运行.
请注意,这仅适用于一张桌子.如果表中有一个表(类似的东西<td> ... <td></td> ... </td>),这将会破坏.你必须调整它以记住它的深度.
另一种方法是使用miyagawa优秀的Web :: Scraper.这样,我们的代码就少了很多:
#!/usr/bin/perl
use strictures;
use Web::Scraper;
use 5.012;
my $s = scraper {
process "td", "foo[]" => 'HTML'; # grab the raw HTML for all <td>s
result 'foo'; # return the array foo where the raw HTML is stored
};
my $html = do { local $/ = undef; <DATA> }; # read HTML from __DATA__
my $res = $s->scrape( $html ); # scrape
say for @$res; # print each line of HTML
Run Code Online (Sandbox Code Playgroud)
这种方法也可以处理像魅力这样的多维表.
| 归档时间: |
|
| 查看次数: |
1077 次 |
| 最近记录: |