###実現したいこと
オライリー・ジャパンから出版されている書籍の一覧を読み込み、木構造を作成するようなプログラムを作成しています。
オライリー・ジャパン発行書籍一覧
HTML::TreeBuilderを用い、実行しようとした際に以下のエラーメッセージが発生しました。
###発生している問題・エラーメッセージ
$ perl oreilly_catalog.pl
と実行すると
Cannot decode string with wide characters at /usr/lib/perl/5.18/Encode.pm line 176.
と表示されます。
###該当のソースコード
oreilly_catalog.pl
Perl
1 1 #!/usr/bin/perl -w 2 2 use strict; 3 3 use LWP::Simple; 4 4 use HTML::TreeBuilder; 5 5 use Encode; 6 6 #use encoding 'utf-8';# 使用しているプラットフォームにあわせてください。 7 7 #binmode(STDERR, ':raw :encoding(utf-8)');# 同上 8 8 use utf8; 9 9 binmode(STDOUT, ':utf8'); 10 10 binmode(STDERR, ':utf8'); 11 11 12 12 my $url = 'http://www.oreilly.co.jp/catalog/'; 13 13 my $page = get( $url ) or die $!; 14 14 $page = decode('utf-8', $page); 15 15 my $p = HTML::TreeBuilder->new_from_content( $page ); 16 16 17 17 my @links = $p->look_down( 18 18 _tag => 'a', 19 19 href => qr{^ \Qhttp://www.oreilly.co.jp/BOOK/\E \w+ / $}x 20 20 ); 21 21 22 22 my @rows = map { $_->parent->parent } @links; 23 23 24 24 my @books; 25 25 for my $row (@rows) { 26 26 my %book; 27 27 my @cells = $row->look_down( _tag => 'td' ); 28 28 next if ($#cells != 2); 29 29 $book{isbn}= $cells[0]->as_trimmed_text; 30 30 $book{title}= decode('utf8', $cells[1]->as_trimmed_text); 31 31 $book{price}= $cells[2]->as_trimmed_text; 32 32 $book{price}=~ s/^\//; 33 33 $book{price}=~ s/,//g; 34 34 35 35 $book{url}= get_url( $cells[1] ); 36 36 push @books, \%book; 37 37 } 38 38 39 39 sub get_url { 40 40 my $node = shift; 41 41 my @hrefs = $node->look_down( _tag => 'a'); 42 42 return unless @hrefs; 43 43 my $url = $hrefs[0]->attr('href'); 44 44 $url =~ s/\s+$//; 45 45 return $url; 46 46 } 47 47 48 48 $p = $p->delete; # $pはもう要らない 49 49 50 50 { 51 51 my $count = 1; 52 52 my @perlbooks = sort { $a->{price} <=> $b->{price} } 53 53 grep { $_->{title} =~ /perl/i } @books; 54 54 print $count++, "\t", $_->{price}, "\t", $_->{title},"\n" for @perlbooks; 55 55 } 56 56 57 57 { 58 58 my @perlbooks = grep { $_->{title} =~ /perl/i } @books; 59 59 my @javabooks = grep { $_->{title} =~ /java/i } @books; 60 60 my $diff = @javabooks - @perlbooks; 61 61 print "Perl本は" . @perlbooks . "冊あり、Java本は" . @javabooks . 62 62 "冊あります。 Perl本よりもJava本の方が" . $diff . "冊多いです。\n"; 63 63 } 64 64 65 65 66 66 67 67 for my $book ( @books ) { 68 68 next unless $book->{title} =~ /Google Hacks/; # Google Hacksのみ処理する。 69 69 my $url = $book->{url}; 70 70 my $page = get( $url ); 71 71 $page = decode('utf-8', $page); 72 72 my $tree = HTML::TreeBuilder->new_from_content( $page ); 73 73 my ($pubinfo) = $tree->look_down( _tag => 'b' );# タイトルの<b>タグを検索する。 74 74 $pubinfo = $pubinfo->parent->parent; # 書籍情報の取得 75 75 my $info = decode('utf8', $pubinfo->as_trimmed_text); 76 76 my ($pages) = $info =~ /(\d+)ページ/; 77 77 my ($original) = $info =~ /原書:(.+)$/; 78 78 my ($date) = $info =~ /(\d+年\d+月)発行/; 79 79 80 80 print "\nページ数:$pages\n原書タイトル:$original\n発行年月:$date\n"; 81 81 82 82 my ($dummy, $img_node) = $tree->look_down( _tag => 'img' ); 83 83 my $img_url = $url . $img_node->attr('src'); 84 84 my $cover = get( $img_url ); 85 85 # ここで$coverをファイルに保存します。 86 86 open(OFH, ">cover.gif"); 87 87 binmode(OFH); 88 88 print OFH $cover; 89 89 close(OFH); 90 90 $tree = $tree->delete; 91 91 } 92
###試したこと
Cannot decode string with wide characters の直し方 – 放置演算子
を参考に、
Perl
1〜〜省略〜〜 2 9 binmode(STDOUT, ':utf8'); 3 10 binmode(STDERR, ':utf8'); 4 11 $string = Encode::_utf8_off($string); 5〜〜省略〜〜
として
$ perl oreilly_catalog.pl
と実行すると
Global symbol "$string" requires explicit package name at oreilly_catalog.pl line 11.
Global symbol "$string" requires explicit package name at oreilly_catalog.pl line 11.
Execution of oreilly_catalog.pl aborted due to compilation errors.
となったので
Perl
1〜〜省略〜〜 2 9 binmode(STDOUT, ':utf8'); 3 10 binmode(STDERR, ':utf8'); 4 11 my $string = Encode::_utf8_off($string); 5〜〜省略〜〜
にして
$ perl oreilly_catalog.pl
と実行すると
Global symbol "$string" requires explicit package name at oreilly_catalog.pl line 11.
Execution of oreilly_catalog.pl aborted due to compilation errors.
となりました。
翻訳すると
明示的なパッケージ名が必要
とのことだそうですが、具体的にどうすればいいのか分かりません。
###補足情報(言語/FW/ツール等のバージョンなど)
$ perl -v
とすると
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
(with 44 registered patches, see perl -V for more detail)
Copyright 1987-2013, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
です。
###余談
Ctrl+Uでサイトを見た結果
view-source:http://www.oreilly.co.jp/catalog/
では
本のタイトル、値段等の情報は見られませんでしたが、
このプログラムは正しく動作するのでしょうか?
何卒よろしくお願いします。