2

私はPerlを使用してサイトに接続し、そのHTMLを解析し、タグの間にあるinnerHTMLを抽出しています。高度な概念を試す前に、まず簡単な概念を試しています。

LWP :: UserAgentを使用して、サイトへのHTTP GETリクエストを作成し、応答を受信します。

次のように応答を配列に格納します。

@res = ($ua->request($req))->content;

編集:解析するHTML:

<div class="new"> this is Line 1 </div>
<div>
      this is Line 2 </div>

ここで、HTTP応答の各行を解析し、タグ間のテキストを抽出します。

foreach $line(@res)
{
chomp $line;
if($line =~ /<div[^>]*?>(.*)<\/div>/)
{
    $match = $1;
    print OUTPUT $match."\n";
}
}

上記のコードスニペットの問題は次のとおりです。

  1. 最初に成功した一致のinnerHTMLのみに一致します。成功したすべての一致が出力されるわけではありません。理由はわかりませんが、ループは私に従って機能しているはずです。変数$matchの値は、一致が成功するたびにキャプチャバッファの内容で上書きされる必要があります。

  2. タグが複数行にまたがっている場合、innerHTML間のテキストを抽出することはできません。最初の行に開始divタグ、次の行にinnerHTML、次の行に終了divタグがあります。

この投稿ではHTMLを書くことができないので、説明をしました。

どんな助けでもいただければ幸いです。

4

3 に答える 3

3

堅牢なHTMLパーサーの使用:

use HTML::TreeBuilder::XPath qw();

my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse($http_response->content);

for my $node ($tree->findnodes('//div')) {
    print $_->as_HTML for @{ $node->content_array_ref };
}
于 2012-06-26T11:26:18.730 に答える
1

行からすべての一致を抽出するには、プログレッシブ一致を使用する必要があります。たとえば、$lineが文字列Thisisdivの後にspanを保持し、これを抽出する場合、This is divの後にaspanが続く場合は、次のように使用できます。

print "$2\n" while $line =~ /<(.*?)>(.*?)<\/\g{1}>/g;

もちろん、ネストされた要素も解析する必要があります。これは、はるかに困難でトリッキーになります。2番目の問題として、複数行モードが必要です。最良の方法は、\s修飾子を使用することです。これにより。が強制されます。改行にも一致します。または、ファイルハンドルをスカラー変数に直接割り当てることで、すべての行をマージできます。

于 2012-06-26T05:18:36.500 に答える
0

十分に汎用的で実際のアプリケーションに適したものにしたい場合は、もう少し複雑です。

<script>まず、と</script>タグの間のコンテンツを削除する必要があります。

次に、開始タグに常に同じテキストが含まれていると想定することはできません。たとえば、のテキストは。<span class="myclass">のテキストとまったく同じではありません</span>

<something>タグの種類に関係なく、すべてのタグを削除し、タグを削除することをお勧めします<script>

おそらく、1つの超スマートな正規表現だけでは解決できません。複数の正規表現を使用して作業を行うことをお勧めします。

これは私がまとめた小さなスクリプトで、cnn.comで正常に機能します(重要な入力のサンプルとして)。うまく印刷するために改行を保持しようとし、空の行を削除しましたが、明らかに、これはすべて必要ではない可能性があります。

\nまた、ダミーの文字列で非表示にすることで、ここでいくつかの汚いトリックを行いました\\\\NN(グローバルに置き換える<script>ことは他の方法では機能しません)。

    my $text = "";
    foreach my $line (@res)
    {
        chomp $line;
        $text .= $line . "\\\\NN"; # Hiding the \n's
    }

    $text =~ s/(<script(\s[^<]*)?>.*?<\/script>)//gi;
    $text =~ s/<.*?>/ /g;

    # Beautify it... :)
    $text =~ s/\s{2,}/ /g;
    $text =~ s/\s*\\\\NN\s*/\\\\NN/g;
    $text =~ s/(\\\\NN){2,}/\\\\NN/g;
    $text =~ s/\\\\NN/\n/g;

    print $text."\n";
于 2012-06-26T07:59:43.600 に答える