テキストの文字種分割の補足の補足

split して空文字列を grep で抜くほうがベターかと思います。

テキストの文字種分割の補足 - daily dayflower

「ベターかと思います」とか断言してしまいましたが,

正規表現の最後に最後に「|.」を足すだけでも良いかもしれませんね。)

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

最近の人気記事はてなブックマーク
人力検索はてな注目の人力検索注目のアンケート注目のいわし
注目の写真はてなフォトライフ
おすすめ日記はてなダイアリー
はてなのサービス
ポケットはてな
はてラボ (実験サービス)
もっとはてな
新着情報

アヒャ,あんまりうまくいってない(笑)ですが,まあこんな感じになります。