4

WWW::Mechanizeと を使用して、古い vBulletin フォーラムからテキストを抽出しようとしていますMojo::DOM

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->at($div_id)->all_textすると、途切れのない行にすべてが表示されるため、投稿で引用されているものと元のものを区別するのが難しくなります.

を使用$dom->at($div_id)->textするとすべての子要素がスキップされるため、引用されたテキストとスポイラーは取り上げられません。

のバリエーションを試しまし$dom->at($div_id)->children('div')->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仕事を得ていません。

どんな助けでも大歓迎です。

4

2 に答える 2

3

Mojo::DOM のソースを見ると、基本的にこのall_textメソッドは DOM を再帰的に走査し、すべてのテキストを抽出します。そのソースを使用して、独自の DOM 関数のウォークを記述します。その再帰関数は、単一の文字列を返すことに依存します。あなたの場合、必要なコンテキストで配列を返すようにすることができます。

編集:

IRC に関するいくつかの議論の後、Web スクレイピングの例が更新されました。http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#Web_scraping

于 2012-12-28T22:14:51.450 に答える
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;
}
于 2012-12-29T17:26:08.477 に答える