テキストの文字種分割の補足の補足
テキストの文字種分割の補足 - daily dayflower
split
して空文字列をgrep
で抜くほうがベターかと思います。
「ベターかと思います」とか断言してしまいましたが,
(正規表現の最後に最後に「
Perl で日本語テキストを字種分割|.
」を足すだけでも良いかもしれませんね。)
そうです,(ケースによっては)それで充分で,速いです。
% perl bench.pl Benchmark: timing 1000000 iterations of by_match, by_split... by_match: 63 wallclock secs (62.42 usr + 0.13 sys = 62.55 CPU) @ 15987.21/s (n=1000000) by_split: 72 wallclock secs (71.36 usr + 0.11 sys = 71.47 CPU) @ 13991.88/s (n=1000000)
思ったより差は小さいですね。
ケースによっては,というのは,正規表現でトラッピングできてないトークンを文字ごとに分割するかどうか,と,そのようなトークンを特別視するかどうか,ということにかかってきます。
「文字ごとに分割するか」というのは単純な例ですが,
original: zーーーあyxルーラでう、う9 10AB.DE「"GH'」★で漢字をカ・ナ食ったー!?MJD39?。 by_match: z, ー, ー, ー, あ, yx, ルーラ, でう, 、, う, 9, , 10, AB, ., DE, 「", GH, '」, ★, で, 漢字, を, カ, ・, ナ, 食, ったー, !?, MJD, 39?, 。, by_split: z, ーーー, あ, yx, ルーラ, でう, 、, う, 9, , 10, AB, ., DE, 「", GH, '」, ★, で, 漢字, を, カ, ・, ナ, 食, ったー, !?, MJD, 39?, 。,
このようになります。これは,やりたいことによりけり。前者のほうが適している場合も多いでしょう。
「トラッピングできていないトークンを特別視するか」というのは,たとえば,
my @tokens = split / (...) /xms, $src; while (@tokens) { my ($unhandled, $handled) = splice @tokens, 0, 2; ...... }
このように,正規表現でとらえ切れなかった部分は $unhandled
にやってきますので,ここで特別な処理(エラーをだすとか)をしたい場合に使うことができます。
文字種による tokenize とは離れてしまいますが,このことを利用してなんちゃってスクレイパーを書いてみると,
#!/usr/bin/perl use strict; use warnings; my $html = do { local $/; <> }; # slurp my @tokens = split m{ ( < .*? > ) }xmso, $html; push @tokens, q{}; # last token my $in_h2 = 0; while (@tokens) { my $pcdata = shift @tokens; my $tag = shift @tokens; if ($in_h2) { print $pcdata; } if ($tag eq '<h2>') { $in_h2 = 1; } elsif ($tag eq '</h2>') { $in_h2 = 0; print "\n"; } }
こんな感じで書けて,
% perl scrape.pl index.html 最近の人気記事はてなブックマーク 人力検索はてな注目の人力検索注目のアンケート注目のいわし 注目の写真はてなフォトライフ おすすめ日記はてなダイアリー はてなのサービス ポケットはてな はてラボ (実験サービス) もっとはてな 新着情報
アヒャ,あんまりうまくいってない(笑)ですが,まあこんな感じになります。