稲沢市よりお届けしてます。

Perlをはじめとしたプログラミング周りのあれこれについて。Perl、最近書いてないなぁ。

Perl=>WWW::Mechanizeでの日本語の扱いでつまづき、解決した件。

WWW::Mechanizeを使いこなしたい

オライリーの『SPIDERING HACKS』を買ってからというもの、「MADにWEBの情報を集めて整理してエグイ感じで発信してやるぜ、グヘヘ」と思っていたが、いまいち進んでいない。


一番の原因は、日本語マルチバイトの壁。


使っていても「Wide Characterうんたら」というエラーが出たり、文字コードの扱いがうまくいっていなくて欲しい結果が得られない。


Perlモチベーションが高まってしまった今日、久しぶりにMechを使ってみた。


やろうとしたことは、非常にシンプル。
(1)ターゲットURLにアクセス
(2)URL内のリンクを辿ってページ遷移
(3)ページ遷移先のコンテンツを表示する



ポータルみたいなのを作るベースとしての動作確認のつもりで行った作業。

#!/usr/bin/perl
#
# Mechでスクレイピング♪(use encoding使用。こいつは非推奨なやり方だよ。良い子は真似しちゃダメ。)

use strict;
use warnings;
use utf8;
use WWW::Mechanize;

use encoding 'cp932';
binmode(STDERR, ':raw :encoding(cp932)');

# ターゲットURLをセットする
my $url = 'http://www.akb48.co.jp/';

my $agent = WWW::Mechanize->new();

# ホームページを取得する
$agent->get($url);

# スケジュールページを取得する
$agent->follow_link(text => 'スケジュール');

print $agent->{content}, "\n";


とりあえず動けばいいぢゃんという感じで上のスクリプトを作ってみた。


でも、encodingプラグマを使って文字コードエンコードとかデコードを理解せずに
うやむやでやってる感が否めない。


dankogaiが非推奨してたのも気になるし->『perl - use encoding; #は黒歴史』


そこで encodingプラグマ無しにして探求してみた。


Encode使って何とかなるはずだ。


・・・で、なんとかなった。

#!/usr/bin/perl
#
# Mechでスクレイピング♪(utf8プラグマなし。ファイル保存形式はUTF8-N)

use strict;
use warnings;
use WWW::Mechanize;

#use encoding 'cp932';
#binmode(STDERR, ':raw :encoding(cp932)');
use Encode;

# ターゲットURLをセットする
my $url = 'http://www.akb48.co.jp/';

my $agent = WWW::Mechanize->new();

# ホームページを取得する
$agent->get($url);

# スケジュールページを取得する=>Mechに送る前にデコード
$agent->follow_link(text => decode('utf8', 'スケジュール'));

# 標準出力先であるWinXPコマンドプロンプトの文字コードにエンコード
print encode('cp932', $agent->{content}, "\n");


んでもって、utf8プラグマを使って「スケジュール」のdecode を無くすのが一番よさげ。

#!/usr/bin/perl
#
# Mechでスクレイピング♪(utf8プラグマあり。ファイル保存形式はUTF8-N)

use strict;
use warnings;
use utf8;
use WWW::Mechanize;

#use encoding 'cp932';
#binmode(STDERR, ':raw :encoding(cp932)');
use Encode;

# ターゲットURLをセットする
my $url = 'http://www.akb48.co.jp/';

my $agent = WWW::Mechanize->new();

# ホームページを取得する
$agent->get($url);

# スケジュールページを取得する
$agent->follow_link(text => 'スケジュール');

# 標準出力先であるWinXPコマンドプロンプトの文字コードにエンコード
print encode('cp932', $agent->{content}, "\n");


半年ぐらい前から悩んでいたところが、だいぶスッキリしたー。


これで、スクレーピングし放題だなw