【问题标题】:Trouble pinpointing child elements while using Mojo::DOM使用 Mojo::DOM 时无法准确定位子元素
【发布时间】:2012-12-13 22:48:57
【问题描述】:

我正在尝试使用 WWW::MechanizeMojo::DOM 从旧的 vBulletin 论坛中提取文本。

vBulletin 不使用 HTML 和 CSS 进行语义标记,我无法使用 Mojo::DOM->children 获取某些元素。

这些 vBulletin 帖子的结构因内容而异。

单条消息:

<div id="postid_12345">The quick brown fox jumps over the lazy dog.<div>

引用另一个用户的单条消息:

<div id="postid_12345">
    <div>
    <table>
        <tr>
            <td>
            <div>Quote originally posted by Bob</div>
            <div>Everyone knows the sky is blue.</div>
            </td>
        </tr>
    </table>
    </div>

 I disagree with you, Bob. It's obviously green.
</div>

带有剧透的单条消息:

<div id="postid_12345">
    <div class="spoiler">Yoda is Luke's father!</div>
</div>

引用另一位用户的单条消息,带有剧透:

<div id="postid_12345">
    <div>
    <table>
        <tr>
            <td>
            <div>Quote originally posted by Fred</div>
            <div class="spoiler">Yoda is Luke's father!</div>
            </td>
        </tr>
    </table>
    </div>
    <div class="spoiler">No waaaaay!</div>
</div>

假设上面的 HTML 和一个包含必要帖子 ID 的数组:

for (@post_ids) {
    $mech->get($full_url_of_specific_forum_post);
    my $dom = Mojo::DOM->new($mech->content);
    my $div_id = 'postid_' . $_;

    say $dom->at($div_id)->children('div')->first;
    say $dom->at($div_id)->text;
}

使用$dom-&gt;at($div_id)-&gt;all_text 可以让我看到一条完整的线,这让我很难分辨帖子中引用的内容和原创内容。

使用$dom-&gt;at($div_id)-&gt;text 会跳过所有子元素,因此不会拾取引用的文本和剧透。

我尝试了$dom-&gt;at($div_id)-&gt;children('div')-&gt;first 的变体,但这给了我一切,包括HTML。

理想情况下,我希望能够提取每个帖子中的所有文本,每个子元素都在自己的行中,例如

 POSTID12345:
 + Quote originally posted by Bob
 + Everyone knows the sky is blue. 
 I disagree with you, Bob. It's obviously green. 

我是 Mojo 的新手,对 Perl 不熟悉。我想自己解决这个问题,但是在查看文档并摆弄了几个小时之后,我的大脑一片混乱,我不知所措。我只是不明白Mojo::DOMMojo::Collections 是如何工作的。

任何帮助将不胜感激。

【问题讨论】:

    标签: perl mojolicious


    【解决方案1】:

    查看 Mojo::DOM 的源代码,基本上 all_text method 递归遍历 DOM 并提取所有文本。使用该源代码编写您自己的遍历 DOM 函数。它的递归函数依赖于返回单个字符串,在你的函数中,你可以让它返回一个包含你需要的任何上下文的数组。

    编辑:

    经过对 IRC 的一些讨论,网络抓取示例已更新,它可能会帮助您指导您。 http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#Web_scraping

    【讨论】:

    • +1 你在过去几天里的回答对我指出正确的方向非常有帮助。谢谢!
    【解决方案2】:

    有一个扁平化 HTML 树的模块,HTML::Linear扁平化 HTML 树 的目的解释有点冗长乏味,所以这里有一张显示xpathify 工具的输出的图片,与该模块绑定:

    如您所见,HTML 树节点变为单个键/值列表,其中键是该节点的 XPath,值是节点的文本属性。 只需几次击键,这就是您使用 HTML::Linear 的方式:

    #!/usr/bin/env perl
    use strict;
    use utf8;
    use warnings;
    
    use Data::Printer;
    use HTML::Linear;
    
    my $hl = HTML::Linear->new;
    $hl->parse_file(q(vboard.html));
    
    for my $el ($hl->as_list) {
        my $hash = $el->as_hash;
        next unless keys %{$hash};
        p $hash;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-03
      • 2018-07-13
      • 2016-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      相关资源
      最近更新 更多