という無謀な試み。「所属事務所」というメタデータを付加することで、面白い傾向が見えてくるといいなーと。ただ、この業界は事務所の移り変わりが激しいからなあ・・・あまり意味はないのかもしれない。今年は何人移籍したのやら。エリたんもバオバブだしなー。
とりあえず、昔書いた変換コードをパッケージにする。
URIエスケープを含んだ文字コード変換とか色々 - XXXannex
use Exporter; package EEncode; use strict; use warnings; use Encode; use URI::Escape; #use Smart::Comments; our @ISA = qw(Exporter); our @EXPORT = qw(convert_s2s convert_s2e convert_s2eu convert_s2E convert_s2Eu convert_e2s convert_e2e convert_e2eu convert_e2E convert_e2Eu convert_eu2s convert_eu2e convert_eu2eu convert_eu2E convert_eu2Eu); my $ESCAPED = 1; # normal URI-escaped my $ESCAPED_ALL = 2; # all URI-escaped my $ESCAPED_WP = 4; # URI-escaped without prefix '%' (must be used with $ESCAPED or $ESCAPED_ALL) my $ENCODE_SJIS = 8; my $ENCODE_EUC = 16; my $ENCODE_UTF8 = 32; # alias our $ES = $ENCODE_SJIS; our $EE = $ENCODE_EUC; our $EU = $ENCODE_UTF8; my %ENCODER = ( $ENCODE_SJIS => find_encoding('sjis'), $ENCODE_EUC => find_encoding('euc-jp'), $ENCODE_UTF8 => find_encoding('utf-8'), ); sub ___convert{ my ($str, $frome, $toe, $from, $to) = @_; my $value = $str; ### args : ($str, $frome, $toe, $from, $to) ## at first unescape characer if($frome & $ESCAPED_WP){ $value =~ s/(..)/%$1/g; } if($frome & $ESCAPED){ $value = URI::Escape::uri_unescape($value); } ## encode if "from" is specified if($from and $to){ ### from encoder : $ENCODER{$from} ### to encoder : $ENCODER{$to} Encode::_utf8_off($value); $value = $ENCODER{$to}->encode($ENCODER{$from}->decode($value)); Encode::_utf8_off($value); } ## escape again if($toe & $ESCAPED){ $value = URI::Escape::uri_escape($value); } elsif($toe & $ESCAPED_ALL){ $value = URI::Escape::uri_escape($value, '\x00-\xff'); } if($toe & $ESCAPED_WP){ $value =~ s/%//g; } return $value; } ## wrapper function: ## s : string ## u : without prefix ## e : escaped ## E : escaped_all sub convert_s2s { ___convert($_[0], 0, 0, $_[1], $_[2]); } sub convert_s2e { ___convert($_[0], 0, $ESCAPED, $_[1], $_[2]); } sub convert_s2eu { ___convert($_[0], 0, $ESCAPED|$ESCAPED_WP, $_[1], $_[2]); } sub convert_s2E { ___convert($_[0], 0, $ESCAPED_ALL, $_[1], $_[2]); } sub convert_s2Eu { ___convert($_[0], 0, $ESCAPED_ALL|$ESCAPED_WP, $_[1], $_[2]); } sub convert_e2s { ___convert($_[0], $ESCAPED, 0, $_[1], $_[2]); } sub convert_e2e { ___convert($_[0], $ESCAPED, $ESCAPED, $_[1], $_[2]); } sub convert_e2eu { ___convert($_[0], $ESCAPED, $ESCAPED|$ESCAPED_WP, $_[1], $_[2]); } sub convert_e2E { ___convert($_[0], $ESCAPED, $ESCAPED_ALL, $_[1], $_[2]); } sub convert_e2Eu { ___convert($_[0], $ESCAPED, $ESCAPED_ALL|$ESCAPED_WP, $_[1], $_[2]); } sub convert_eu2s { ___convert($_[0], $ESCAPED|$ESCAPED_WP, 0, $_[1], $_[2]); } sub convert_eu2e { ___convert($_[0], $ESCAPED|$ESCAPED_WP, $ESCAPED, $_[1], $_[2]); } sub convert_eu2eu { ___convert($_[0], $ESCAPED|$ESCAPED_WP, $ESCAPED|$ESCAPED_WP, $_[1], $_[2]); } sub convert_eu2E { ___convert($_[0], $ESCAPED|$ESCAPED_WP, $ESCAPED_ALL, $_[1], $_[2]); } sub convert_eu2Eu { ___convert($_[0], $ESCAPED|$ESCAPED_WP, $ESCAPED_ALL|$ESCAPED_WP, $_[1], $_[2]); }
次に作業メモ(1)でリストアップした名前からWikipediaページのエントリーをとって来る。中島愛みたいに「(声優)」と付いている名前が案外多いので、ここのスクリプトを若干変更。
my @names_wiki = uniq map{ sleep 1; # to avoid DoS print STDERR "scraping $_ ... \n"; my $l = scraper { process '//div[@id="mw-pages"]//li/a', 'names[]', => { 'name' => ['TEXT', sub {s/ \(.+//;} ], 'link' => '@href' }; result 'names'; }->scrape(new URI($_)); $l ? map {"$_->{name}\t$_->{link}"} @$l : (); } @$uris;
こんな感じに。んで、2カラム目を使って本文をダウンロードします。
while read name link; do base=`echo $link | sed -e 's/.*\///; s/_(.*//'` echo "wget -O ${base}.html '$link'; sleep 1" done < sy.out > dl.sh
うーん、メチャメチャ遅い。プロセス起動のオーバーヘッドがこんなにかかるとはなあ。同じ処理をperlでやると超早い。
$ time perl -nle '@l=split(/\t/); $base=$l[1]; $base=~s/.*\///; $base=~s/_\(.*//; print "wget -O ${base}.html \"$l[1]\"; sleep 1"' sy.out > /dev/null real 0m0.101s user 0m0.077s sys 0m0.000s
$ time while read name link; do base=`echo $link | sed -e 's/.*\///; s/_(.*//'`; echo "wget -O ${base}.html '$link'; sleep 1"; done < sy.out > /dev/null real 4m26.659s user 2m36.290s sys 1m59.463s
まあ、それはともかくとして。
色々試行錯誤したいので、直接読み取らずに一旦ダウンロードしておきます。そして保存したhtmlファイルに対して、所属事務所っぽい物をとって来る。この辺はヒューリスティックにならざるを得ないが・・・上手い方法はあるんだろうか。
声優さんの一覧+所属事務所の情報と言うことであれば、こういうサイトも見つけた。
http://jp.jade-voice.com/actor/actress.php
割と網羅されてるっぽいけど・・・ここでもプロダクションエースは総スルーで笑った。エロゲー声優が入ってないのは仕方ないか・・・。でも、補助的には使えそう。
use strict; use warnings; use File::Basename; use FindBin; use lib "$FindBin::RealBin/../lib"; use EEncode; my $infile = shift; die "open [$infile] failed" unless -f $infile; print $infile, "\t"; print convert_e2s(basename($infile, '.html')), "\t"; open my $fh, '<', $infile or die; my @l = <$fh>; close $fh; #1. check profile table for(my $i=0; $i<@l; $i++){ if($l[$i] =~ m{<th.*(所属|事務所).*</th>}){ my $pro = $l[++$i]; $pro =~ s/<.*?>//g; print $pro; exit; } } #2. check text foreach(@l){ tr/\x0A\x0D//d; s/<.*?>//g; foreach(split(/。/)){ if(/所属|事務所/){ print "$_\t"; } } } #3. check 18X-game foreach(@l){ s/<.*?>//g; if(/アダルトゲーム/){ print "所属不明(エロゲー)\n"; exit; } } #4. check net foreach(@l){ s/<.*?>//g; if(/ネット声優/){ print "ネット声優\n"; exit; } } print "\n";
こういう、いかにもなクイックハック感は嫌いじゃない(笑)
実行結果はこんな感じ。
%E3%80%86%E9%87%8E%E6%BD%A4%E5%AD%90.html 〆野潤子 賢プロダクション %E3%81%82%E3%81%8A%E3%81%8D%E3%81%95%E3%82%84%E3%81%8B.html あおきさやか ぷろだくしょんバオバブ %E3%81%82%E3%81%8B%E3%81%84%E3%81%A8%E3%81%BE%E3%81%A8.html あかいとまと C&Oプロダクション %E3%81%82%E3%81%8D%E3%82%84%E3%81%BE%E3%81%8B%E3%81%8A%E3%82%8B.html あきやまかおる カレイドスコープ %E3%81%82%E3%81%8D%E3%82%84%E3%81%BE%E3%82%8B%E3%81%AA.html あきやまるな 81プロデュース %E3%81%82%E3%81%95%E3%82%8A%E2%98%86.html あさり☆ 所属不明(エロゲー) %E3%81%82%E3%81%A5%E3%81%BF%E3%82%8C%E3%81%84%E3%81%8B.html あづみれいか %E3%81%82%E3%82%8A%E3%81%99.html ありす 所属不明(エロゲー)
ま、概ねおっけーな感じ?もしかしたら事務所名の表記ゆれ(ぷろだくしょんバオバブ = バオバブみたいな)があるかもしれないので、そこは注意ですね。