先日の記事において我々はキーワード付与のための強力な正規表現式を手にしています。 そこで今回、これを利用して記事内容からタグ候補を自動的に抽出できるようにしてみました。 当サイトには 170 弱のタグが登録されている程度('05年11月現在)ですが、 なかなか好調で記事作成時のタグ入力作業が随分と楽になりました。
;# ++piroli, '05/11/14
MT::Template::Context->add_container_tag('TagsAutoDiscovery' => &tags_auto_discovery);
sub tags_auto_discovery {
my ($ctx, $args, $cond) = @_;
;# Tags Auto Discovery does work only when '[?]' is appeared as keyword.
;# When keywords of the entry is blank or has any words, do nothing.
my $entry = $ctx->stash ('entry')
or return $ctx->_no_entry_error ('MT'. $ctx->stash ('tag'));
$entry->keywords =~ m/^[?]$/
or return $entry->keywords;
;# retrieving parameters and set default values
# count *** NOT YET IMPLEMENTED ****
# my $count = $args->{count} || 0;
;# retrieving the regexp pattern of keywords
my $re;
if (defined (my $regexp_file = $args->{regexp_file})) {
;# @see <$MTInclude file="..."$>
$re = MT::Template::Context::_hdlr_include (
$ctx, {'file' => $args->{regexp_file}}, $cond);
} elsif (defined (my $regexp_template = $args->{regexp_template})) {
;# you can use the file which is built with Index Template
;# @see <$MTLink template="..."$>
my $file_path = MT::Template::Context::_hdlr_link (
$ctx, {'template' => $args->{regexp_template}}, $cond);
my $site_url = $ctx->stash('blog')->site_url;
my $site_path = $ctx->stash('blog')->site_path;
$file_path =~ s/Q$site_urlE/$site_path//;
$file_path =~ s//+///g;
$re = do $file_path;
} elsif (defined (my $regexp_module = $args->{regexp_module})) {
;# it may be the performance issue when too many tags
;# but you can control this behaviour by parameters :)
;# @see <$MTInclude module="..."$>
$re = MT::Template::Context::_hdlr_include (
$ctx, {'module' => $args->{regexp_module}}, $cond);
} else {
;# it may be the performance issue when too many tags
;# and be called with using all args as default values :(
$re = eval tags_as_regexp ($ctx, $args);
}
$ctx->error ('MT'. $ctx->stash ('tag'). ': no regexp is specified.') if (! $re);
;# build contents within container tag
defined (my $content = $ctx->stash('builder')->build ($ctx, $ctx->stash ('tokens')))
or return $ctx->error ($ctx->errstr);
;# convert $content to EUC temporally because regexp is written in EUC
use Jcode;
my $original_charset = getcode ($content);
$content = Jcode::convert ($content, 'euc', $original_charset);
;# should not keywordnize in these tags
my %ignore_tags = ();
map { $ignore_tags{lc $_} = 1; } split /,/, 'pre,textarea';
defined $args->{ignore_tags}
and map { $ignore_tags{lc $_} = 1; } split /,/, $args->{ignore_tags};
defined $args->{apply_tags}
and map { $ignore_tags{lc $_} = 0; } split /,/, $args->{apply_tags};
;# Parse the $content for retrieving the text areas that should be given the keywords
my $keywordnize = 0;
my %keyword_list = ();
use HTML::Parser;
my $html_parser = HTML::Parser->new (
start_h => [ sub {
my ($tagname) = @_;
$ignore_tags{$tagname} && $keywordnize++;
} => 'tagname'],
end_h => [ sub {
my ($tagname) = @_;
0 < $keywordnize && $ignore_tags{$tagname} && --$keywordnize;
} => 'tagname'],
text_h => [ sub {
my ($text) = @_;
if ($keywordnize == 0) {
$text =~ s{($re)}{
my $kw = $1;
$keyword_list{$kw}++;
$kw;
}egx;
}
} => 'text'],
default_h => [""]);
$html_parser->parse ($content);
$html_parser->eof;
;# Set the discovered keywords as entry's new one.
my $keywords = join ' ',
sort { $keyword_list{$b} <=> $keyword_list{$a} } keys %keyword_list;
$keywords = Jcode::convert ($keywords, $original_charset, 'euc');
$entry->keywords ($keywords);
$entry->save;# :-)
return $entry->keywords;
}
MTTagsAutoDiscovery
<MTTagsAutoDiscovery> コンテナタグは、
コンテナ内に含まれる文章から regexp_XXX で指定された正規表現式を使ってタグの抽出を行い、
発見された単語を MovableType 管理画面の記事の投稿画面のキーワード欄に設定します。
またコンテナタグは、そこに含まれるコンテクストに関係なく、常にそのエントリのキーワードを返します。
つまり <$MTEntryKeywords$> と同じです。
regexp_fileregexp_templateregexp_module
regexp_file、regexp_template、regexp_module が何れも指定されていない場合、
内部的にデフォルトパラメータを用いて MTTagsAsRegexp を呼び出します。
そのため、構築のたびに正規表現式の生成が行われるため、
タグ数が増えた場合にパフォーマンス上の問題となる可能性があります。
ignore_tagsapply_tagsこれらの指定はデフォルトのignore_tags < ignore_Tags < apply_tags の順に優先されます。
<MTTagsAutoDiscovery> タグを追加します。
regexp_file、regexp_template、regexp_module の詳細については、
はてなキーワードよろしく記事文中のタグを自動リンクする
"正規表現式の生成とテンプレートタグの修正"の節を参照してください。
内容(BODY)と追記(extend)部分からタグ候補の抽出を行う MTTagsAutoDiscovery コンテナは常にキーワード文字列を返すのでコメントアウトしている <!-- <MTTagsAutoDiscovery regexp_template="Tags Regexp"> <$MTEntryBody$> <$MTEntryMore$> </MTTagsAutoDiscovery> -->
下書き状態でもキーワード抽出できればいいのですが… その方が便利そうです。
寄せられたコメント (全 16 件中、最新 5 件まで表示しています)
METAタグへの記述は,普通に<MTEntryTags>テンプレートタグを書いて対応しています。確か。
MT4.2でエントリーの内容を元にタグを自動で生成するプラグインを探して、
こちらにたどりつきました。こちらで紹介している内容はMT4.2でも問題なく動作しますでしょうか?
また、ここではキーワードとして抽出するようになってますが、メタとして自動生成することも可能でしょうか?
お答えいただけるとうれしいです。
「Tagwire Pluginで記事内容からタグ候補を自動的に抽出する」
機能を便利に利用していますが、
最近、既存のキーワードに無い変な文字を抽出してくるようになりました。
毎回特定の文字ではないのですが、決まって一文字で、
日常使わないような見た事もないような文字の場合が多いようです。
Jcode.pmは"Jcode.pm,v 2.6 2006/07/02 07:56:06"で
Tagwireのタグは全て標準のタグと競合しないようにリネームしてあります。
他にチェックすべきポイントはありますか?
教えていただけると助かります。宜しくお願いします。
これと何らかの競合を起こしているように思えますが,
ちょっと調査しきれていません。
あと,タグ候補の自動抽出は同様に可能とも思いますが,
おそらく専用にプラグインなりを作って対処することになりそうです。
チョイチョイ☆って感じでは難しいんじゃないでしょうか?
あれ以来、便利に利用させていただいておりますが、
MTを3.3にアップデートして以来、
キーワード欄に表示されるタグ候補が「,」(コンマ)から始まり表示されます。
,サッカー,シュート,パス…とこんな感じです。
タグ候補を修正してタグ欄にコピーする際に調整すれば利用上の不都合はないのですが、
気になっていたので報告させていただきました。
また、3.3で装備された機能を用いて、Tagwaireを使用せずにタグ候補を自動的に抽出する方法はありますか?
できたらいいな程度の要望なのですが、お知恵を拝借できれば幸いです。