複数の文字コードを利用する難しさ
Google へ検索クエリーを送り、取得した HTML を表示する。
下記の2つのスクリプトを試してみた。最初のスクリプトは、ファイルの文字コードが EUC-JP。もうひとつは、UTF-8 とした。
最初のスクリプトは、入力されるデータは UTF-8 で、出力形式は EUC-JP である。
#!/opt/local/bin/perl -w use strict; use LWP 5.64; use URI; use Encode; use encoding 'euc-jp'; binmode(STDOUT, ':raw :encoding(euc-jp)'); binmode(STDERR, ':raw :encoding(euc-jp)'); my $browser = LWP::UserAgent->new; my $url = URI->new('http://www.google.co.jp/search'); # クエリーの生成 $url->query_form( 'hl' => 'ja', 'q' => encode('utf8', 'はてな'), 'btnG' => encode('utf8', 'Google 検索'), 'lr' => '' ); my $response = $browser->get($url); print decode('utf-8', $response->content);
ファイルの文字コードが UTF-8 のスクリプトは次のものである。
#!/opt/local/bin/perl -w use strict; use LWP 5.64; use URI; use Encode; binmode(STDOUT, ':raw :encoding(euc-jp)'); binmode(STDERR, ':raw :encoding(euc-jp)'); my $browser = LWP::UserAgent->new; my $url = URI->new('http://www.google.co.jp/search?'); # クエリーの生成 $url->query_form( 'hl' => 'ja', 'q' => 'はてな', 'btnG' => 'Google 検索', 'lr' => '' ); my $response = $browser->get($url); print $response->content;
実行結果は次の通り。はじめのスクリプトは、
% ./google.pl Use of uninitialized value in substitution iterator at /opt/local/lib/perl5/site_perl/5.8.8/URI/_query.pm line 16. Use of uninitialized value in substitution iterator at /opt/local/lib/perl5/site_perl/5.8.8/URI/_query.pm line 16. (中略) "\x{fffd}" does not map to euc-jp at ./google.pl line 23. "\x{fffd}" does not map to euc-jp at ./google.pl line 23. "\x{fffd}" does not map to euc-jp at ./google.pl line 23.
というエラーになる。
ふたつめのスクリプトは、
./google_utf8.pl <html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"><title>403 Forbidden</title><style><!--body {font-family: arial,sans-serif}div.nav {margin-top: 1ex}div.nav A {font-size: 10pt; font-family: arial,sans-serif}span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}div.nav A,span.big {font-size: 12pt; color: #0000cc}div.nav A {font-size: 10pt; color: black}A.l:link {color: #6f6f6f}A.u:link {color: green}//--></style><script><!--var rc=403;//--></script></head><body text=#000000 bgcolor=#ffffff><table border=0 cellpadding=2 cellspacing=0 width=100%><tr><td rowspan=3 width=1% nowrap><b><font face=times color=#0039b6 size=10>G</font><font face=times color=#c41200 size=10>o</font><font face=times color=#f3c518 size=10>o</font><font face=times color=#0039b6 size=10>g</font><font face=times color=#30a72f size=10>l</font><font face=times color=#c41200 size=10>e</font> </b><td> </td></tr><tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff><b>Error</b></td></tr><tr><td> </td></tr></table><blockquote><H1>Forbidden</H1>Your client does not have permission to get URL <code>/search?hl=ja&q=%E3%81%AF%E3%81%A6%E3%81%AA&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=</code> from this server. (後略)
二つ目のスクリプトから出力された結果に含まれていた
/search?hl=ja&q=%E3%81%AF%E3%81%A6%E3%81%AA&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=
に、http://www.google.co.jp を追加すれば、ブラウザで正しく検索結果が表示されたので、ただしく文字列は URL エンコードされている。しかし、最初のスクリプトはエラーが表示される。
これは、URI ではなく、Encode モジュールの問題なのだろか?