【Perl 文字化け解決】Wide character in print atといふエラーが原因だったー
こんばんは、Perl48です。
引き続き、
「アマゾンのゲーム売れ筋ランキングのゲームタイトルデータを引っこ抜きたーい」
の文字化け解消に取り組んでまいります。
まずは、前回までのソース
#!/usr/bin/perl -wuse lib 'C:/usr/cpan/build/Web-Scraper-0.32-VSDMOU/lib';
use Web::Scraper;
use URI;# ゲームタイトル部分を gtitle という名前で取るスクレイパーを作成
my $scraper = scraper {
process 'table.zg .productTitle', 'gtitle' => 'TEXT';
};# amazon.co.jpのTVゲームベストセラーページのURLオブジェクトを、
my $uri = new URI('http://www.amazon.co.jp/gp/bestsellers/videogames’);# 先ほどのスクレイパーに渡す。(スクレイピングされる)
my $res = $scraper->scrape($uri);print $res->{gtitle}; # 何が出るかな?
「ははーん、文字化けといえば、Jcode.pm だろ?」
という期待を裏切らない安易な発想で、
#!/usr/bin/perl -wuse lib 'C:/usr/cpan/build/Web-Scraper-0.32-VSDMOU/lib';
use Web::Scraper;
use URI;
use Jcode;# ゲームタイトル部分を gtitle という名前で取るスクレイパーを作成
my $scraper = scraper {
process 'table.zg .productTitle', 'gtitle' => 'TEXT';
};# amazon.co.jpのTVゲームベストセラーページのURLオブジェクトを、
my $uri = new URI('http://www.amazon.co.jp/gp/bestsellers/videogames');# 先ほどのスクレイパーに渡す。(スクレイピングされる)
my $res = $scraper->scrape($uri);print $res->{gtitle}; # 何が出るかな?
・・・残念ながら先ほどと結果は変わらず。
あきらめの境地でエラー画面を眺めていると、
『wide character in print at』の文字が目に飛び込んでくる!
「これだっー!」
早速ググル先生に質問しまくる。
ググル先生はエラーメッセージのコピペ検索に対しての
回答の精度がめちゃくちゃ高いから好きだ。
秀逸な記事はたくさんあったけど、
一番わかりやすかったのは、下記の記事
UTF8フラグとPerlIOレイヤ
どうやらutf-8 のテキストをprintしようとしてるから
エラーが出ちまうらしい。
まずは、utf-8のフラグが立ってるかどうかの確認をするため、
下記のソースを記述(もともとのprint文は一旦コメントアウト)
#!/usr/bin/perl -wuse lib 'C:/usr/cpan/build/Web-Scraper-0.32-VSDMOU/lib';
use Web::Scraper;
use URI;# ゲームタイトル部分を gtitle という名前で取るスクレイパーを作成
my $scraper = scraper {
process 'table.zg .productTitle', 'gtitle' => 'TEXT';
};# amazon.co.jpのTVゲームベストセラーページのURLオブジェクトを、
my $uri = new URI('http://www.amazon.co.jp/gp/bestsellers/videogames');# 先ほどのスクレイパーに渡す。(スクレイピングされる)
my $res = $scraper->scrape($uri);#print $res->{gtitle}; # 何が出るかな?→一旦コメントアウト
print utf8::is_utf8($res->{gtitle}) ? 'flagged' : 'no flag';
の中の
Wide character な文字列はそのまま出力すると文句を言われるというわけです。
回避するには、PerlIOレイヤを使うか、UTF8フラグを落とします。
を参考に、ソースにPerlIOレイヤを追加
#!/usr/bin/perl -wuse lib 'C:/usr/cpan/build/Web-Scraper-0.32-VSDMOU/lib';
use Web::Scraper;
use URI;# ゲームタイトル部分を gtitle という名前で取るスクレイパーを作成
my $scraper = scraper {
process 'table.zg .productTitle', 'gtitle' => 'TEXT';
};# amazon.co.jpのTVゲームベストセラーページのURLオブジェクトを、
my $uri = new URI('http://www.amazon.co.jp/gp/bestsellers/videogames');# 先ほどのスクレイパーに渡す。(スクレイピングされる)
my $res = $scraper->scrape($uri);binmode(STDOUT, ":utf8");# PerlIOレイヤ
print $res->{gtitle}; # 何が出るかな?
すると、エラーは消えた!!
が、
またまたググル先生に相談。
ググル先生は、何時に相談しても答えてくれる素敵なヒトだ。
で、行き着いたのが
wakaponさんの超☆掃き溜め帳
どうすればいいかというと、またまたencodingを使う。encodingにソースコードの文字コードを指定する。ソースコードがshiftjisであった場合、次のようにする。
で、ソースを以下のように
#!/usr/bin/perl -wuse lib 'C:/usr/cpan/build/Web-Scraper-0.32-VSDMOU/lib';
use Web::Scraper;
use URI;
use encoding qw(shiftjis);# ゲームタイトル部分を gtitle という名前で取るスクレイパーを作成
my $scraper = scraper {
process 'table.zg .productTitle', 'gtitle' => 'TEXT';
};# amazon.co.jpのTVゲームベストセラーページのURLオブジェクトを、
my $uri = new URI('http://www.amazon.co.jp/gp/bestsellers/videogames');# 先ほどのスクレイパーに渡す。(スクレイピングされる)
my $res = $scraper->scrape($uri);print $res->{gtitle}; # 何が出るかな?
そして、ついに・・・
wakaponさんの2006年の記事に助けられましたー。
ありがとうございます!
残すは、繰り返し処理の部分だぁぁぁ!!
今日はもう寝まーす。