ラテン語版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