【问题标题】:perl extract text between html tags using regexperl 使用正则表达式在 html 标签之间提取文本
【发布时间】:2013-09-23 23:45:42
【问题描述】:

我是 Perl 新手,我试图提取字符串中所有 <li> </li> 标记之间的文本,并使用正则表达式或拆分/加入将它们分配到一个数组中。

例如

my $string = "<ul>
                  <li>hello</li>
                  <li>there</li>
                  <li>everyone</li>
              </ul>";

所以这段代码...

foreach $value(@array){
    print "$value\n";
}

...结果如下:

hello
there
everyone

【问题讨论】:

  • 对 HTML 使用正则表达式不是一个好主意。见this answer
  • 是的,正则表达式是一个非常错误的工具。
  • regex 不是一个可怕的工具,如果它适合您的需要,请使用它,可能比 HTML 解析器更快。使用 HTML 解析器,您可以知道其有效的 HTML,并且可以遍历树。
  • 是的,我认为你对 OP 太苛刻了。他/她不是要求一个复杂的 html 解析器,而是一些合理的东西。只需在\n 上拆分字符串并搜索&lt;li&gt;(.+?)&lt;/li&gt;&lt;li&gt;([^&lt;]) 之类的内容。我会回答,但我太努力忘记 PERL。

标签: html regex perl tags


【解决方案1】:

注意:不要使用正则表达式解析 HTML。

第一个选项是使用HTML::TreeBuilder 完成的,它是许多可供使用的 HTML 解析器之一。您可以访问上面提供的链接并阅读文档并查看给出的示例。

use strict;
use warnings;
use HTML::TreeBuilder;

my $str 
   = "<ul>"
   . "<li>hello</li>"
   . "<li>there</li>"
   . "<li>everyone</li>"
   . "</ul>"
   ;

# Now create a new tree to parse the HTML from String $str
my $tr = HTML::TreeBuilder->new_from_content($str);

# And now find all <li> tags and create an array with the values.
my @lists = 
      map { $_->content_list } 
      $tr->find_by_tag_name('li');

# And loop through the array returning our values.
foreach my $val (@lists) {
   print $val, "\n";
}

如果您决定在这里使用正则表达式(我不推荐)。你可以做类似的事情..

my $str
   = "<ul>"
   . "<li>hello</li>"
   . "<li>there</li>"
   . "<li>everyone</li>"
   . "</ul>"
   ;

my @matches;
while ($str =~/(?<=<li>)(.*?)(?=<\/li>)/g) {
  push @matches, $1;
}

foreach my $m (@matches) {
   print $m, "\n";
}

输出:

hello
there
everyone

【讨论】:

    【解决方案2】:

    注意:Do not use regular expressions to parse HTML.

    hwnd 已经提供了一种 HTML Parser 解决方案。

    但是,对于基于 css 选择器的更现代的 HTML 解析器,您可以查看 Mojo::DOMMojocast episode 5 有一个内容丰富的 8 分钟介绍视频。

    use strict;
    use warnings;
    
    use Mojo::DOM;
    
    my $html = do {local $/; <DATA>};
    
    my $dom = Mojo::DOM->new($html);
    
    for my $li ($dom->find('li')->text->each) {
        print "$li\n";
    }
    
    __DATA__
    <ul>
      <li>hello</li>
      <li>there</li>
      <li>everyone</li>
    </ul>
    

    输出:

    hello
    there
    everyone
    

    【讨论】:

      最近更新 更多