【问题标题】:Parse html using Perl使用 Perl 解析 html
【发布时间】:2011-10-10 02:15:45
【问题描述】:

我有以下 HTML-

<div>
   <strong>Date: </strong>
       19 July 2011
</div>

我一直在使用 HTML::TreeBuilder 来解析使用标签或类的 html 的特定部分,但是前面提到的 html 让我难以尝试仅提取日期。

比如我试过-

for ( $tree->look_down( '_tag' => 'div'))
{ 
my $date  = $_->look_down( '_tag' => 'strong' )->as_trimmed_text;

但这似乎与之前使用的 &lt;strong&gt;. 冲突 我希望只解析“2011 年 7 月 19 日”。我已阅读有关 TreeBuilder 的文档,但找不到这样做的方法。

如何使用 TreeBuilder 做到这一点?

【问题讨论】:

    标签: html perl html-parsing


    【解决方案1】:

    您可以通过从&lt;div&gt; 中删除&lt;strong&gt; 中的文本来解决此问题:

    my $div      = $tree->look_down( '_tag' => 'div' );
    my $div_text = $div->as_trimmed_text;
    if ( my $strong = $div->look_down( '_tag' => 'strong' ) ) {
        my $strong_text = $strong->as_trimmed_text;
        my $date        = $div_text;
        $date =~ s/$strong_text\s*//;
    }
    

    【讨论】:

    • 它说它不能在'my $strong_text = $div->look_down('_tag' => 'strong')->as_trimmed_text;'上的未定义值上调用方法线。请记住,这是使用“for”循环 - 'for ($tree->look_down('_tag' => 'div')) {' 也许这会导致错误?
    • for 循环中使用look_down 应该没问题。您能否提供一个您尝试解析的 HTML 示例(包含多个 divstrong 元素)?
    • Premium !

      他们冻结

    • 我更新了我的代码,检查&lt;strong&gt; 是否存在于&lt;div&gt; 中。
    • 似乎有一个语法错误,说明缺少 '}' 但它似乎仍然没有得到我想要的。
    【解决方案2】:

    看起来HTML::Element::content_list() 是您想要的功能。后代节点将是对象,而文本将只是文本,因此您可以使用 ref() 过滤以仅获取文本部分。

    for ($tree->find('div')) {
      my @content = grep { ! ref } $_->content_list;
      # @content now contains just the bare text portion of the tag
    }
    

    【讨论】:

      【解决方案3】:

      “转储”方法对于找到绕过 HTML::TreeBuilder 对象的方法非常有用。

      这里的解决方案是获取您感兴趣的元素的父元素(在本例中为

      )并遍历其内容列表。您感兴趣的文本将是纯文本节点,即列表中不引用 HTML::Element 对象的元素。
      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      use HTML::TreeBuilder;
      
      my $tree = HTML::TreeBuilder->new;
      
      $tree->parse(<<END_OF_HTML);
      <div>
         <strong>Date: </strong>
             19 July 2011
      </div>
      END_OF_HTML
      
      my $date;
      
      for my $div ($tree->look_down( _tag => 'div')) {
        for ($div->content_list) {
          $date = $_ unless ref;
        }
      }
      
      print "$date\n";
      

      【讨论】:

      • 看起来不错,但有没有办法绕过对 html 进行硬编码?如果我从 html 文件中读取,我会打开 'foo.csv' 吗?
      • 对不起,那只是为了演示目的。我假设您知道如何使用 HTML::TreeBuilder 解析数据。 HTML::TreeBuilder 对象有一个 parse_file 方法(您将在文档中看到)。
      猜你喜欢
      • 2015-12-02
      • 1970-01-01
      • 2012-12-12
      • 2013-08-20
      • 1970-01-01
      • 2011-06-03
      • 2012-10-26
      • 1970-01-01
      相关资源
      最近更新 更多