読者です 読者をやめる 読者になる 読者になる

のんびり読書日記

日々の記録をつらつらと

Wikipediaのリダイレクトを使って同義語とれるかな

wikipediaは同義語の単語(「ASIA」と「アジア」とか)は、代表的な単語にリダイレクトするようになっています。つまりリダイレクト関係にある単語は、大抵は同じ意味であることが期待されます。そこでこのリダイレクト関係を使って、同義語を抽出してみようと思います。

実際に作成したスクリプトは以下の通りです。

#!/usr/bin/perl
#
# wikipediaのリダイレクトを使って同義語を抽出
#
# Usage:
# % bzcat jawiki-latest-pages-articles.xml.bz2 | ./redirect_words.pl > result.tsv
#
# 参考ページ: 
# [を] Wikipediaのキーワードリンクを使って関連語データを作ってみた
# http://chalow.net/2007-06-09-3.html
#

use strict;
use warnings;
use Encode qw(encode decode);

sub word_ok {
    my $word = shift;
    return unless $word;
    return if $word =~ m{[:\|\n\t\[\]]};;
    return if $word =~ m{^[\#\s]};;
    $word =~ s/\s*\(.+?\)$//;
    return if $word =~ /一覧$/;
    return if $word =~ /\d+\d+日$/;
    return if $word =~ /^\d{4}年$/;
    return if $word =~ /Wikipedia:/;
    return if $word =~ /Portal:/;
    return if $word =~ /その他/;
    return if $word =~ /の比較/;
    return if $word =~ /(曖昧さ回避)/;
    return if $word =~ /#/;
    return $word;
}

my $flag = 0;
my $content;
while (my $line = <STDIN>) {
    chomp $line;
    if (!$flag && $line =~ m{<page>}) {
        $flag = 1
    }
    if ($flag) {
        $content .= $line;
    }
    if ($flag && $line =~ m{</page>}) {
        my ($title) = $content =~ m{<title>([^<]+)<};
        $title = word_ok($title);
        if ($title) {
            my @words;
            push @words, $title;

            my ($redirect_large) = $content =~ m/#REDIRECT \[\[(.+?)\]\]/;
            $redirect_large = word_ok($redirect_large);
            push @words, $redirect_large if $redirect_large;

            my ($redirect_small) = $content =~ m/{{[Rr]edirect\|(.+?)}}/;
            if ($redirect_small) {
                my @redirects;
                foreach my $word (split /\|/, decode 'utf-8', $redirect_small) {
                    $word = word_ok(encode 'utf-8', $word);
                    push @words, $word if $word;
                }
            }
            if (scalar(@words) > 1) {
                print join "\t", @words;
                print "\n";
            }
        }
        $flag = 0;
        $content = '';
    }
}

抽出結果はこちら。(ファイルサイズが9M近くあるので注意)

AFTA	ASEAN自由貿易地域
AFTC	自動車公正取引協議会
AFU	アフリナット国際航空

こんなのとか、

明石焼き    玉子焼
明石西公園  兵庫県立明石西公園
明石西高等学校  兵庫県立明石西高等学校
明石中宮    明石の姫君

こんなのが取れてます。まあ大抵は1文字違いの単語とかで、編集距離で判定した方が良さそうなものばかりですが。

使い道はなさそうですが、メモとして置いておきます。