黒縁眼鏡は海を飛ぶ

IT中心にそこはかとなく

PerlでWebスクレイピング入門

Let's Webスクレイピング

正規表現で一生懸命パターンマッチしていると、徐々に心が蝕まれていく実感があったのでHTML::TagParser使って楽をします。


想定HTML

テストするために人様のサイトに負荷をかけるのは忍びないので、自前で用意します。

<html>
  <head>
    <title>テストページ</title>
  </head>
  <body>
    <div class="header">
      ヘッダですよ
    </div>
    <div class="main">
      <div class="content">
        本文がごにょごにょ
        <img src="photo.png">
        <div class="link">
          <a href="http://example.com">リンク1</a>
        </div>
        <div class="link">
          <a href="http://example.com">リンク2</a>
        </div>
        <div class="link">
          <a href="http://example.com">リンク3</a>
        </div>
      </div>
      <ul class="side">
        <li>
          <a href="http://example.com">サイドバー</a>
        </li>
      </ul>
    </div>
  </body>
</html>

一応Webスクレイピングがネタなので、HTTPでhtml引っこ抜いてくる体で進めます。


まずはhtmlを取得

HTTP::TagParser->new('$URL')みたいな書き方すればそれで済むらしいのですが、お勉強がてらLWP::UserAgent使ってみる。

実は初めて使ったLWP::UserAgent

#!/usr/bin/env perl

use strict;
use warnings;
use LWP::UserAgent;
use HTML::TagParser;     # 今回の主役

my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => 'http://ryoana.com/test.html');
my $res = $ua->request($req);

取得が成功していれば$res->contentで取得したhtmlが確認できます。


Parseする

ではHTML::TagParser使っていきましょう。

# 上の続きから…
my $html = HTML::TagParser->new('$res->content');

# titleタグの中身を取得して表示
my $title = $html->getElementsByTagName('title');
print $title->innerText . "\n";

# div要素(content)内にあるdiv要素(link)内にあるaタグに記載されてるURLとテキストを取得して表示(混乱)
my @links = $html->getElementsByClassName('link');
my $subhtml;
my $a;
my $url;
my $text;
for my $link (@links) {
    $subhtml = $link->subTree;
    $a = $subhtml->getElementsByTagName('a');
    $url = $a->getAttribute('href');
    $text = $a->innerText;
    print "$text: $url\n";
}

# sideと定義されているclassは何のタグで宣言されているか知る
my $tagname = $html->getElementsByClassName('side')->tagName;
print "$tagnameタグ\n";

実行すると以下の結果が得られます。

テストページ
リンク1: http://example.com
リンク2: http://example.com
リンク3: http://example.com
ulタグ


所感

正規表現でやるの辛すぎるのでいいと思いました。

HTML::TagParser使いましたが、ナウい奴はこれ使うんだぜとか、そもそもおまえ勘違いしてね?みたいなご指摘ありましたら教えてください。泣いて喜びます。


謝辞

HTML::TagParser - HTMLソースの解析/属性値やinnerTextの取得
perlでHTMLを解析して欲しい情報を抽出するためのコードをメモ