Perl:删除列表<;ul>;从第段开始。HTML解析

Perl:删除列表<;ul>;从第段开始。HTML解析,html,perl,parsing,Html,Perl,Parsing,我有一堆html文件,我需要从中提取文本,但不是列表的内容。 html就像 <html> <Head> <title>intranet mycompany</title> </head> <body> <div>blah</div> <p>the text i need to extract

我有一堆html文件,我需要从中提取文本,但不是列表的内容。 html就像

<html>

    <Head>
        <title>intranet mycompany</title>
    </head>

    <body>
        <div>blah</div>
        <p>the text i need to extract
            <br>
            <ul>
                <li>stuff i don't want.</li>
                <li>more stuff i don't want.</li>
            </ul>More text i need to exctract.</p>
    </body>

</html>

企业内部网
废话
我需要提取的文本

  • 我不想要的东西
  • 更多我不想要的东西
我需要解释更多的文本

我真的想要一些关于如何从段落中获取文本的建议,而不是从列表中获取文本。任何建议都是有必要的

问候,,
Jombo.

看看CPAN forHTML解析器,你会得到很好的解析器,比如,等等。

最困难的一点是数据跨越多行。如果你要把所有的行连接成一个大字符串,一个简单的正则表达式,比如

s/<ul>.*<\/ul>//g
s/
    *//g
应该这样做。

使用狭窄;
use strictures;
use HTML::TreeBuilder::XPath qw();
my $dom = HTML::TreeBuilder::XPath->new_from_content(q(<html> … </body>));
my ($ul) = $dom->findnodes('//ul');
$ul->delete;
my $extract = $dom->findvalue('//p');
# " the text i need to extract  More text i need to exctract. "
使用HTML::TreeBuilder::XPath qw(); my$dom=HTML::TreeBuilder::XPath->new_from_content(q(…); my($ul)=$dom->findnodes('//ul'); $ul->删除; my$extract=$dom->findvalue('//p'); #“我需要提取的文本更多我需要提取的文本。”
这里有一种方法可以去除
数据。由于调用文本处理程序时,HTML::Parser不知道它在文档中的位置,因此必须找到某种方法来提供该信息

只需告诉为每个起始元素调用的
start\u处理程序
,对打开的
进行注释,并让
end\u处理程序
删除该注释。然后,您可以利用
文本处理程序中的信息,这样它就可以跳过
    s
中的文本节点

#!/usr/bin/perl -w
use strict;
use HTML::Parser;

my $text = '';
my $parser = HTML::Parser->new(
  start_h => [ \&start_handler, "self,tagname" ],
  end_h   => [ \&end_handler,   "self,tagname" ],
  text_h  => [ \&text_handler,  "self,dtext" ],
);

sub start_handler {
  my ($self, $tag) = @_;
  $self->{_private}->{'ul'} = 1 if ( $tag eq 'ul' ); # make a note
}

sub end_handler {
  my ($self, $tag) = @_;
  $self->{_private}->{'ul'} = 0 if ( $tag eq 'ul' ); # remove the note
}

sub text_handler {
  my ($self, $dtext) = @_;
  unless ($self->{_private}->{'ul'}) {
    # only if we're not inside the <ul>
    $text .= $dtext;
  }
}
$parser->parse_file('test.html');
print $text;
#/usr/bin/perl-w
严格使用;
使用HTML::解析器;
我的$text='';
my$parser=HTML::parser->new(
start\u h=>[\&start\u处理程序,“自我,标记名”],
end\u h=>[\&end\u处理程序,“自我,标记名”],
text\u h=>[\&text\u处理程序,“self,dtext”],
);
子启动处理器{
我的($self,$tag)=@;
$self->{u private}->{ul'}=1如果($tageq'ul');#做个笔记
}
副端处理器{
我的($self,$tag)=@;
$self->{u private}->{ul'}=0如果($tag eq'ul');#删除注释
}
子文本处理程序{
我的($self,$dtext)=@;
除非($self->{u private}->{'ul'}){
#除非我们不在
    $text.=$dtext; } } $parser->parse_文件('test.html'); 打印$text;
这不是使用正则表达式解析HTML的好建议。请使用现有的CPAN模块。切勿使用正则表达式解析XML/HTML/CSV文件。使用现有的模块,它们通常是成熟、稳定和经过良好测试的。@briandfoy:如果您按照“如果您要将所有行合并为一个大字符串”的说明进行操作,那么这个示例非常有效。(但在单行模式下,它同样有效:)我同意,如果你想解析HTML,正则表达式不是一个好办法,但是如果你需要一个快速而肮脏的方法来清除文件的某些部分,学习HTML解析器可能无法有效地利用时间。@minitech如果数据中有多个ul,则您将删除第一个ul开头到最后一个ul结尾之间的所有内容。因此,它确实适用于所提供的示例,该示例仅为1 ul,但很可能不适用于实际数据(请注意,文章开头说明了“列表的内容”,我在这里看到了足够多的复数形式,表明确实有可能出现多个列表;--)。谢谢您的评论。有人能提供一些示例代码吗?我能得到这一段的内容。但是列表仍然会在其中。@user1343861-只要搜索(右上角)“[perl]HTML解析器”,您就会在这里找到关于StackOverflow的很多信息。顺便说一下,这不是HTML。在HTML中,UL元素不能出现在P元素中。@casperOne-当您(作为主持人)删除其他答案时,请友好地在该答案中添加注释,并说明确切原因。非常感谢。那你呢??我会把“=1”和“=0”改成“+”和“-”你是对的。我忘了。它应该是
$self->{u private}->{ul'}++if($tageq'ul')和`$self->{u private}->{ul'}--if($tageq'ul');`。非常感谢。