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を解析して欲しい情報を抽出するためのコードをメモ