【问题标题】:extracting html between tags using perl使用perl在标签之间提取html
【发布时间】:2013-05-23 19:29:45
【问题描述】:

我想提取字符串或文件标记之间的所有 html,我一直在使用 (perl) 模块 html::parser,我认为这将是一项简单的任务,但结果却非常棘手?我发现了一些有效但不知道如何将结果保存到字符串的代码?任何帮助表示赞赏 或者,如果您可以向我展示一些关于如何使用 HTML::TokeParser 或类似方法实现此目的的代码。

谢谢

my $content=<<EOF;
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <title>Some title goes here</title>
 </head>
 <body bgcolor="#FFFFFF">
   <div id="leftcol">
     menu column
  </div>
  <div id="body">
   <p>some text goes here some text goes here<br />
    some text goes here some text goes here</p>
   <p><strong>some header</strong></p>
   <p>some text goes here some text goes here<br />
   some text goes here some text goes here</p>
    <p><img src="img.gif" /> image here</p>
   <p><strong>some header</strong></p>
   <p>some text goes here some text goes here<br />
   some text goes here some text goes here</p>
   </div>
    <div id="rightcol">
   news column
    </div>
 </body>
</html>
EOF


my $p = HTML::Parser->new( api_version => 3 );
$p->handler( start => \&start_handler, "self,tagname,attr" );
$p->parse($content);
exit;

sub start_handler {
    my $self = shift;
    my $tagname  = shift;
    my $attr = shift;
    my $text = shift;
    return unless ( $tagname eq 'body' );
    $self->handler( start => sub { print shift }, "text" );
    $self->handler( text =>  sub { print shift }, "text" );
    $self->handler( end  => sub {
    my ($endtagname, $self, $text) = @_;
         if($endtagname eq $tagname) {
         $self->eof;
         } else {
              print $text;
        }
    }, "tagname,self,text");
 }

如果我修改上面的子例程开始文本和结束处理程序,如下所示

为什么这些变量中的文本没有保存到我的?

$self->handler( start => sub {  my ($text) = @_; $inner_body = $inner_body. $text; }, "text" );
$self->handler( text =>  sub {  my ($text) = @_; $inner_body = $inner_body. $text; }, "text" );
$self->handler( end  => sub {
       my ($endtagname, $self, $text) = @_;
       if($endtagname eq $tagname) {
            $self->eof;
           } else {
             $inner_body = $inner_body. $text;
           }
        }, "tagname,self,text");

}

打印 $inner_body; #

希望的输出保存在变量中


   <div id="leftcol">
     menu column
  </div>
  <div id="body">
   <p>some text goes here some text goes here<br />
    some text goes here some text goes here</p>
   <p><strong>some header</strong></p>
   <p>some text goes here some text goes here<br />
   some text goes here some text goes here</p>
    <p><img src="img.gif" /> image here</p>
   <p><strong>some header</strong></p>
   <p>some text goes here some text goes here<br />
   some text goes here some text goes here</p>
   </div>
    <div id="rightcol">
   news column
    </div>

【问题讨论】:

  • 重新更新:你怎么能声称exit(0); print $inner_body; 打印空白?
  • 原因呢?为什么我打印 $inner_body 时缺少一些东西我得到以下 [root@nurelay ~]# ./parsetest [root@nurelay ~]#

标签: html perl html-parsing


【解决方案1】:

你所要做的就是替换

print ...;

$inner_body .= ...;

就我个人而言,我会改用 XML::LibXML。它可以处理 HTML 和 XML(通过使用解析器的适当方法)。您所拥有的是 XHTML(与 XML 兼容),因此我们使用 parse_string 而不是 parse_html_string

use XML::LibXML               qw( );
use XML::LibXML::XPathContext qw( );

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs(h => 'http://www.w3.org/1999/xhtml');

my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($content);
my ($body_node) = $xpc->findnodes('/h:html/h:body', $doc)
   or die;

my $inner_body = join '', map $_->toString(), $body_node->childNodes();
print $inner_body;

【讨论】:

  • 上述方法如何处理无效的html?
  • 再一次,你没有 HTML,你有 XHTML/XML。如果它无效,它不会做任何事情——它甚至不知道它是否有效——但如果它的格式不正确,它就会死掉。如果可能,您可以使用$parser-&gt;recover(...) 让它恢复。
  • invalid XHTML 示例:P 元素内的 DIV 元素。malformed XHTML 示例:缺少结束标记或未转义的 @ 987654327@)
  • 谢谢,我也试试看.. 也有兴趣让 html::parse 工作。
猜你喜欢
  • 2016-11-12
  • 1970-01-01
  • 2014-01-14
  • 2016-09-10
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多