【问题标题】:How to search for text in html-document with Mechanize?如何使用 Mechanize 在 html 文档中搜索文本?
【发布时间】:2015-08-23 05:03:15
【问题描述】:

我在我的 perl 脚本中使用 WWW::Mechanize、HTML::TreeBuilder 和 HTML::Element 来浏览 html 文档。

我想知道如何搜索包含某个字符串作为文本的元素。

这是一个 html 文档的示例:

<html>
  <body>
    <ul>
      <li>
       <div class="red">Apple</div>
       <div class="abc">figure = triangle</div>
      </li>
      <li>
       <div class="red">Banana</div>
       <div class="abc">figure = square</div>
      </li>
      <li>
       <div class="green">Lemon</div>
       <div class="abc">figure = circle</div>
      </li>
      <li>
       <div class="blue">Banana</div>
       <div class="abc">figure = line</div>
      </li>
    </ul>
  </body>
</html>

我想提取文本square。要获得它,我必须搜索具有以下属性的元素:

  • 标签名称是“div”
  • 类是“红色”
  • 内容是文本“香蕉”

然后我需要获取它的父级(&lt;li&gt;-元素),并从父级获取文本以figure = 开头的子级,但这很容易。

我是这样尝试的:

use strict;
use warnings;
use utf8;
use Encode;
use WWW::Mechanize;
use HTML::TreeBuilder;
use HTML::Element;

binmode STDOUT, ":utf8";

my $mech = WWW::Mechanize->new();

my $uri = 'http.....'; #URI of an existing html-document

$mech->get($uri);
if (($mech->success()) && ($mech->is_html())) {
    my $resp = $mech->response();
    my $cont = $resp->decoded_content;
    my $root = HTML::TreeBuilder->new_from_content($cont);

    #this works, but returns 2 elements:
    my @twoElements = $root->look_down('_tag' => 'div', 'class' => 'red');

    #this returns an empty list:
    my @empty = $root->look_down('_tag' => 'div', 'class' => 'red', '_content' => 'Banana');

    # do something with @twoElements or @empty   
}

我必须使用什么来代替最后一个命令来获取想要的元素?

我不是在寻找解决方法(我已经找到了)。我想要的是 WWW::Mechanize、HTML::Tree 或任何其他 cpan-modul 的原生函数。

【问题讨论】:

  • 为什么一定要找红香蕉而不是找正方形?
  • 我正在搜索 1000 多个网站的数据。它们都具有相同的结构。在我的简化示例文档中,“red Banana”是一个修复文本和一个存在于所有 1000 多个文档中的修复类。变化的(以及我试图提取的)在我的示例中是“正方形”和“圆形”)。您可以将“red + Banana”视为键,将“square”视为值。
  • 你可以忘记WWW::Mechanize,只写my $root = HTML::TreeBuilder-&gt;new_from_url($uri)

标签: perl mechanize www-mechanize html-tree


【解决方案1】:

这是伪代码/未经测试的 Perl:

  my @twoElements = $root->look_down('_tag' => 'div', 'class' => 'red');
  foreach my $e ( @twoElements ) {
     next unless $e->content_list->[0] eq 'Banana';
     my $e2 = $e->right;   # get the sibling - might need to try left() depending on ordering
     my ($shape) = $e2->content_list->[0] =~ /figure = (.+)/;

     # do something with shape...

  }

并不完美,但它应该可以帮助您入门,而且它足够通用,可以轻松重复使用。否则替换

    ($shape) = $e2->content_list->[0] =~ /figure = (.+)/;

类似的东西

$shape = 'square' if $e2->content_list->[0] =~ /square/;

这可能会更干净一点:

我的@elements = $root->look_down('_tag' => 'div', 'class' => 'red' ); foreach 我的 $e ( @elements ) { 下一个除非 $e->as_trimmed_text eq 'Banana'; 我的 $e2 = $e-> 对; 我的 ($shape) = $e2->as_trimmed_text =~ /figure = (.+)/;

     # do something with shape...
  }

WWW::Mechanize::TreeBuilder

【讨论】:

  • 这与我使用的解决方法非常相似。但我期待一个更原生的解决方案,即搜索文本的机械化命令。
  • 明确表示:我不确定。我没有找到文本查找功能的明确文档。但是“我没找到”和“它不存在”是两个不同的东西,这也是我必须在这里问的原因。 - 含蓄地:是的。 WWW::Mechanize 和许多 HTML::* 模块涵盖(几乎?)与解析 html 文档有关的所有内容。这就是为什么我猜在文档丛林中一定有一个文本搜索功能。在 html 文档中搜索文本是一项常见任务,因此很难相信开发人员没有创建执行此任务的函数。
  • Mech 主要关注导航,因此大部分方法处理链接、表单和表单元素。您已经使用 TreeBuilder 来解析和查询 HTML,因为当简单的 $content =~ /something/ 不够好时。
  • > 这就是为什么我猜丛林中一定有一个文本搜索功能
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
相关资源
最近更新 更多