gpt4 book ai didi

Perl HTML::Tokeparser 获取标签之间的原始 html

转载 作者:行者123 更新时间:2023-12-02 21:38:58 24 4
gpt4 key购买 nike

我正在使用 TokeParser 来提取标签内容。

...
$text = $p->get_text("/td") ;
...

通常它会返回清理后的文本。我想要的是返回 td/td 之间的所有内容,但包括所有其他 html 元素。怎么做。

我正在使用 this tutorial 中的示例。谢谢

在示例中,

my( $tag, $attr, $attrseq, $rawtxt) = @{ $token };

我相信 $rawtxt 有一些技巧。

最佳答案

HTML::TokeParser 没有内置功能来执行此操作。但是,可以通过查看 <td> 之间的每个标记来实现。单独的。

#!/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>

该程序将解析 __DATA__ 中的 HTML 文档。部分并打印 <td> 之间的所有内容,包括 HTML和</td> 。它将按 <td> 打印一行。 。让我们一步一步地看一下。

  • 阅读 documentation 后,我了解到 HTML::TokeParser 中的每个标记都有一个与之关联的类型。有六种类型:S , E , T , C , DPI 。医生说:

    This method will return the next token found in the HTML document, or undef at the end of the document. The token is returned as an array reference. The first element of the array will be a string denoting the type of this token: "S" for start tag, "E" for end tag, "T" for text, "C" for comment, "D" for declaration, and "PI" for process instructions. The rest of the token array depend on the type like this:

    ["S",  $tag, $attr, $attrseq, $text]
    ["E", $tag, $text]
    ["T", $text, $is_data]
    ["C", $text]
    ["D", $text]
    ["PI", $token0, $text]
  • 我们想要访问$text存储在这些标记中,因为没有其他方法可以获取看起来像 HTML 标签的内容。因此我创建了一个 dispatch table%dispatch 中处理它们。它存储了一堆稍后调用的代码引用。

  • 我们从 __DATA__ 读取了文档,这对于本例来说很方便。
  • 首先,我们需要获取 <td>通过使用get_tag方法。 @nrathaus 的评论向我指出了这一点。它将把解析器移动到开头 <td> 后的下一个标记。 。我们不关心什么get_tag返回,因为我们只想要 <td> 之后的标记.
  • 我们使用方法get_token获取下一个 token 并用它做一些事情:

    • 但我们只想这样做,直到找到相应的结束 </td> 。如果我们看到这一点,我们 next外层while循环标记为TD .
    • 此时, continue block被调用并打印换行符。
    • 如果我们没有到达最后,神奇的事情就会发生:调度表;正如我们之前看到的,标记数组 ref 中的第一个元素保存类型。 %dispatch 中每种类型都有一个代码引用。 。我们调用它并传递完整的数组引用 $token$coderef->(@args) 。我们在当前行打印结果。

      这将产生类似 <strong> 的内容, foo , </strong>每次运行都是如此。

请注意,这仅适用于一张表。如果表中存在表(类似于 <td> ... <td></td> ... </td> ),则会中断。您必须对其进行调整以记住它的深度。


另一种方法是使用宫川的优秀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

这种方法还可以像魅力一样处理多维表。

关于Perl HTML::Tokeparser 获取标签之间的原始 html,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20785388/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com