ラテン語版Wikipediaのデータで遊ぼう


この記事は,ラテン語プログラミング Advent Calendarの15日目の記事になります.
https://qiita.com/advent-calendar/2013/latin

はじめに

どうもはじめまして.気づいたら誕生日にラテン語の教科書が届き,いつの間にかラテン語のテキストを読む会に参加していた@miettalこと「たいしょー」と申します.
http://connpass.com/event/3898/

今回,僕はラテン語版Wikipediaのデータをデータベースに読み込んで,日本語→ラテン語に変換したり,逆にラテン語→日本語に変換したりしてみました.
データベースのコマンドを列挙しているだけなので,主にプログラマの方向けの記事にはなってしまいましたが,ラテン語版Wikipediaに限らず,他の言語版(日本語版,英語版など)でも通用する話だと思うので参考にしていただけたら幸いです.

動機

  • ラテン語-日本語のWeb辞典少ないよね.
  • そもそも不自由で邪悪な辞書は嫌だ.
  • Wikipediaのデータいじるの面白そう.
  • 「Wikipediaは6回のリンクでどの記事にも行ける」って奴あるじゃん.あれ作りたい(参考:[http://gigazine.net/news/20110915_wikitter/:title]).
  • データベースのコマンド覚えるのに良さそう.教科書とかWebに載ってるつまらない例は萎える(例:社員番号,部署名など...).
  • 日本語版Wikipediaはデータの量が多くて,処理に時間かかりそう.ラテン語なら軽い?
  • など...

準備・データの取得

環境のセットアップ

今回,OSはDebian Linuxを使った.
http://www.debian.or.jp/

パッケージのインストール

sudo apt-get install mysql-server mysql-client

ユーザー追加

mysql -u root -p
>mysql GRANT ALL PRIVILEGES ON *.* TO username@localhost IDENTIFIED BY password WITH GRANT OPTION;

作業ディレクトリ

cd
mkdir lawiki
cd lawiki

ダウンロード

ラテン語版Wikipediaのデータのダウンロードに関するページはこちら.SQLファイルとして公開されている.
http://la.wikipedia.org/wiki/Vicipaedia:Dump
そのうち,最新版ダウンロードページはこちら.
http://dumps.wikimedia.org/lawiki/latest/
今回は,日本語→ラテン語,ラテン語→日本語に変換するだけなので,ページ情報と外国版Wikipediaへのリンクに関するものだけをダウンロードする.

  • lawiki-latest-page.sql.gz (ページ情報.本文データや編集履歴は入っていない)
  • lawiki-latest-langlinks.sql.gz (外国版Wikipediaへのリンク.Wikipediaの左サイドバーのやつ)

ダウンロード

wget http://dumps.wikimedia.org/lawiki/latest/lawiki-latest-page.sql.gz
wget http://dumps.wikimedia.org/lawiki/latest/lawiki-latest-langlinks.sql.gz

伸長

gzip --decompress lawiki-latest-page.sql.gz
gzip --decompress lawiki-latest-langlinks.sql.gz

データベースへ読み込む

mysql -u username -p
mysql> create database lawiki;
mysql> use lawiki
mysql> source lawiki-latest-langlinks.sql
mysql> source lawiki-latest-page.sql

データを見てみる

まず,どんな項目があるか見てみる.

mysql> describe page;
+-----------------------+---------------------+------+-----+---------+----------------+
| Field                 | Type                | Null | Key | Default | Extra          |
+-----------------------+---------------------+------+-----+---------+----------------+
| page_id               | int(8) unsigned     | NO   | PRI | NULL    | auto_increment |
| page_namespace        | int(11)             | NO   | MUL | 0       |                |
| page_title            | varbinary(255)      | NO   |     |         |                |
| page_restrictions     | varbinary(255)      | NO   |     | NULL    |                |
| page_counter          | bigint(20) unsigned | NO   |     | 0       |                |
| page_is_redirect      | tinyint(1) unsigned | NO   | MUL | 0       |                |
| page_is_new           | tinyint(1) unsigned | NO   |     | 0       |                |
| page_random           | double unsigned     | NO   | MUL | 0       |                |
| page_touched          | varbinary(14)       | NO   |     |         |                |
| page_latest           | int(8) unsigned     | NO   |     | 0       |                |
| page_len              | int(8) unsigned     | NO   | MUL | 0       |                |
| page_no_title_convert | tinyint(1)          | NO   |     | 0       |                |
+-----------------------+---------------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

mysql> describe langlinks;
+----------+-----------------+------+-----+---------+-------+
| Field    | Type            | Null | Key | Default | Extra |
+----------+-----------------+------+-----+---------+-------+
| ll_from  | int(8) unsigned | NO   | PRI | 0       |       |
| ll_lang  | varbinary(20)   | NO   | PRI |         |       |
| ll_title | varbinary(255)  | NO   |     |         |       |
+----------+-----------------+------+-----+---------+-------+
3 rows in set (0.03 sec)

次に,実際にどんなデータが入っているか見てみる.

mysql> select * from page order by rand() limit 10;
+---------+----------------+---------------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
| page_id | page_namespace | page_title          | page_restrictions | page_counter | page_is_redirect | page_is_new | page_random    | page_touched   | page_latest | page_len | page_no_title_convert |
+---------+----------------+---------------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
|  148945 |              0 | Cuparus             |                   |            0 |                1 |           1 | 0.957458754558 | 20130731114711 |     1897296 |       23 |                     0 |
|   17496 |              0 | 1772                |                   |            0 |                0 |           0 | 0.143781100115 | 20131122233309 |     2409541 |      963 |                     0 |
|  128990 |              0 | Plesiosauria        |                   |            0 |                0 |           0 | 0.684304580113 | 20131121180535 |     2459067 |    15796 |                     0 |
|  183533 |              0 | Basse-Goulaine      |                   |            0 |                1 |           0 | 0.626077621431 | 20130428203814 |     2539476 |       39 |                     0 |
|  106379 |              2 | K123456             |                   |            0 |                0 |           0 | 0.297740073092 | 20130328033141 |     1723685 |      124 |                     0 |
|  133244 |              0 | Mouterhouse         |                   |            0 |                0 |           0 | 0.639352890557 | 20131119153122 |     2461535 |      601 |                     0 |
|   80270 |              0 | Gulielmus_Sancroft  |                   |            0 |                0 |           0 | 0.376759706596 | 20131106121400 |     2435459 |     1053 |                     0 |
|   83696 |              0 | Georgius_J._Stigler |                   |            0 |                0 |           0 | 0.785471178401 | 20131023072455 |     2625379 |      564 |                     0 |
|   67672 |              0 | Manneken_Pis        |                   |            0 |                0 |           0 | 0.631265219803 | 20131111060306 |     2429669 |     1686 |                     0 |
|   69150 |              0 | Aemilianus_Zapata   |                   |            0 |                0 |           0 | 0.030580196108 | 20131013042356 |     2430250 |      722 |                     0 |
+---------+----------------+---------------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
10 rows in set (0.28 sec)

mysql> select * from langlinks order by rand() limit 10;
+---------+---------+---------------------------------------+
| ll_from | ll_lang | ll_title                              |
+---------+---------+---------------------------------------+
|   41633 | pnb     | بوآ: جرمنی                            |
|  120420 | vi      | Bạc hà Âu                             |
|   99017 | yo      | 1064 Aethusa                          |
|   56016 | sr      | Категорија:Умрли 221.                 |
|  187772 | it      | Racines (Francia)                     |
|   45481 | crh     | Kategoriya:1894 senesinde doğğanlar   |
|  168939 | sv      | Brèves                                |
|  195587 | pl      | Vitry-lès-Cluny                       |
|  156134 | ja      | サラダ                                |
|  141856 | fa      | سیارک ۴۸۶۲                            |
+---------+---------+---------------------------------------+
10 rows in set (4.51 sec)

どうやら,pageテーブルはpage_idがページごとに割り振られる番号で,page_titleがページタイトル,langlinksテーブルはll_fromがpage_idのことで,ll_langがどの言語のWikipediaへのリンク,ll_titleがその言語のWikipediaのページタイトルを表している.

データで遊ぶ

さきほど,実際にどんなデータが入っているのかを見たときに,日本語版Wikipediaの「サラダ」の項目に,ラテン語版Wikipediaのpage_idが156134の項目から,外国版Wikipediaのリンクが貼られていることがわかった.そこで,page_idが156134のページタイトルを調べてみる.

mysql> select * from page where page_id = 156134;
+---------+----------------+------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
| page_id | page_namespace | page_title | page_restrictions | page_counter | page_is_redirect | page_is_new | page_random    | page_touched   | page_latest | page_len | page_no_title_convert |
+---------+----------------+------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
|  156134 |              0 | Acetaria   |                   |            0 |                0 |           0 | 0.788934734254 | 20131128082657 |     2475994 |     1055 |                     0 |
+---------+----------------+------------+-------------------+--------------+------------------+-------------+----------------+----------------+-------------+----------+-----------------------+
1 row in set (0.10 sec)

どうやら,「サラダ」のラテン語はAcetariaのらしい.実際Google翻訳にかけたら同じのが出た.正しいみたい.

わざわざ,langlinksテーブルからpage_idを調べてから,pageテーブルでもう1度調べるのは面倒だから
結合させよう.

mysql> select page_title, ll_title from page inner join langlinks on page_id = ll_from where ll_lang = "ja" order by rand() limit 10;
+---------------------------+-----------------------------------------------------+
| page_title                | ll_title                                            |
+---------------------------+-----------------------------------------------------+
| Partidul_Conservator      | 保守党 (ルーマニア)                                 |
| Carmianum                 | カルミアーノ                                        |
| Gadolinium                | ガドリニウム                                        |
| Oceanus_Indicus           | Category:インド洋                                   |
| Alessandro                | アレッサンドロ                                      |
| Petrus_Bérégovoy          | ピエール・ベレゴヴォワ                              |
| Hancock_Comitatus_(Ohium) | ハンコック郡 (オハイオ州)                           |
| 1956_Olympia_Hiemalia     | コルティナダンペッツォオリンピック                  |
| Frida_Kahlo               | フリーダ・カーロ                                    |
| Gens_Antonia              | Category:アントニウス氏族                           |
+---------------------------+-----------------------------------------------------+
10 rows in set (0.11 sec)

おおー結合できてる.これで日本語とラテン語の対応がわかりやすくなった.

どれくらい,対応があるんだろ

mysql> select count(*) from page inner join langlinks on page_id = ll_from where ll_lang = "ja";
+----------+
| count(*) |
+----------+
|    53637 |
+----------+
1 row in set (0.13 sec)

5万項目か.ちょっと調べてみたら,小学生の国語辞典が3万〜4万項目ぐらいだったので,結構な量なのでは.

日本語→ラテン語

できた.

mysql> select page_title, ll_title from page inner join langlinks on page_id = ll_from where ll_lang = "ja" and ll_title = "サラダ";
+------------+-----------+
| page_title | ll_title  |
+------------+-----------+
| Acetaria   | サラダ    |
+------------+-----------+
1 row in set (0.00 sec)

ラテン語→日本語

できた.

mysql> select page_title, ll_title from page inner join langlinks on page_id = ll_from where ll_lang = "ja" and page_title = "Acetaria";
+------------+-----------+
| page_title | ll_title  |
+------------+-----------+
| Acetaria   | サラダ    |
+------------+-----------+
1 row in set (0.06 sec)

最後に

結構簡単にできました.
次はWebのフロントエンドでも作ります.

@kagamiwariさんと内容が結構被ってしまって申し訳ない感
http://qiita.com/kagamiwari/items/2967412e4a7ec9ccfb0e