WikipediaのダンプデータをDBに投入する

 最近、Wikipediaのデータを引用して表示するサービスが良くある。どうやって、実現しているのか?

 Wikipediaには、収録データをHTMLではなくXMLで返してくれるモードもあるが、これはWebブラウザ向けのサービスで、PHPなどでアクセスして取得しようとすると、403のエラーで拒否される。また、「サーバーに負担がかかるので、クローリングしないでください」と明記されている。

 その代わり、Wikipediaの全データをXML形式でダンプしたものが自由にダウンロードできるようになっている。これを読み込んで、自分のデータベースサーバに投入して使えばいいのだ。データベースはMySQLやPostgreSQLに対応し、投入用のツールも用意されている。

 Wikipediaのシステムである、MediaWikiのソースコードも提供されていて、これに含まれているimportDump.phpを使う例が上記のページ上で紹介されているが、こいつはとんでもなく時間がかかる。

 Core2Duo 2.4GHzのMacBookで毎秒2ページ強程度。最新の2009年1月末のダンプデータには108万件あまりのページが含まれていて、全部投入するのに12日以上かかる。

 これでは、とんでもない! と思ったら別の手があると、教えてもらった。同じくMediaWikiのページで提供されている「xml2sql」を使えば、数十分で投入が終わるというのだ。

【おおまかな手順】

(1) xml2sqlをダウンロードする。

 Windows用はバイナリで、Mac OS XやLinuxはソースコードで提供されている。

今回はMac OS X上でmakeした。

(2) データベースとテーブルを用意する。

 今回は、mysqlでデータベースを作成した。テーブル定義のSQLは、Mediawikiのソースコードに含まれている。(maintanance/tables.sql)

(3) WikipediaのXMLダンプデータをダウンロードする。

(4) xml2sqlコマンドで、XMLダンプデータをデータベースに投入できる形式に変換する。

 デフォルトでは、mysqlimportコマンド用の読み込み形式で作成される。

(5) 変換したデータをSQLデータベースに投入する。

 今回はmysqlimportコマンドを使用した。


【実際の手順】

(1) xml2sqlのダウンロード

Xml2sql – Meta

ダウンロードしたソースファイルを解凍し、makeする。

$ tar xvfz xml2sql-0.5.tar.gz

$ cd xml2sql-0.5

$ ./configure

$ make

生成されたxml2sqlコマンドを、パスの通った場所におく

$cp xml2sql /usr/local/bin/

(2) データベースとテーブルを用意する。
 今回は、XAMPPでインストールしたMySQLを使用した。
phpmyadminで、

ユーザー:mwiki(パスワードなし)データベース:mwiki

を作成。
 なお、MediaWikiもインストールする場合は、パスワードを必ず付ける必要がある。また、ユーザー名とパスワードが同じだと受け付けないので、注意。

テーブル定義のSQLは、MediaWikiのソースコードに含まれている。

MediaWiki
$ tar xvfz mediawiki-1.14.0.tar.gz
$ cd mediawiki-1.14.0
$ mysql -u mwiki -D mwiki < maintenance/tables.sql

(3) WikipediaのXMLダンプデータをダウンロードする。

Wikipedia日本語版ダンプのDownload

latestフォルダに最新版のダンプがある。
以下の2種類のファイルがある。
jawiki-latest-abstract.xml = 前ページの要約版 無圧縮で約800MB
jawiki-latest-pages-articles.xml.bz2 = 全ページ版(過去の編集履歴は含まない) 圧縮済みで約850MB。解凍すると3.4GB。

今回は、全ページ版をダウンロードして使用した。解凍すると、

jawiki-latest-pages-articles.xml

というファイルが生成される。

(4) xml2sqlコマンドで、XMLダンプデータをデータベースに投入できる形式に変換する。デフォルトでは、mysqlimportコマンド用の読み込み形式で作成される。

$ xml2sql jawiki-latest-pages-articles.xml

page.txtrevision.txttext.txt

という3つのファイルが生成された。

(5) 変換したデータをSQLデータベースに投入する。 今回はmysqlimportコマンドを使用した。
$ mysqlimport –fields-terminated-by=’\t’ –default-character-set=utf8 -u mwiki -d -L mwiki text.txt

mwiki.text: Records: 1087271 Deleted: 0 Skipped: 0 Warnings: 0

$ mysqlimport –fields-terminated-by=’\t’ –default-character-set=utf8 -u mwiki -d -L mwiki revision.txt

mwiki.revision: Records: 1087271 Deleted: 0 Skipped: 0 Warnings: 2176469

$ mysqlimport –fields-terminated-by=’\t’ –default-character-set=utf8 -u mwiki -d -L mwiki page.txt

mwiki.page: Records: 1087271 Deleted: 0 Skipped: 0 Warnings: 0

ユーザーにパスワードを付けている場合は、上記のコマンドに-pオプションを付ける。



【テーブルについて】

登録された単語(タイトル)から、本文を取得するには、以下のテーブルとカラムを使用する。

pageテーブル

 page_id ページのid

 page_title ページのタイトル

 page_latest 現在のページ内容のID = revision.rev_id

revisionテーブル

 rev_id revisionid

 rev_page このrevisionpage.page_id

 rev_text_id このrevisionのID = text.old_id

textテーブル

 old_id textid

 old_text このtextの内容(本文)

 old_flag old_textのタイプ gzip/utf8/objectの3種類あるが、通常はutf8

—-

【サンプルプログラム】

<?php

$hostname = “localhost”;

$db_name = “mwiki”;

$user_name = “mwiki”;

$password = “”;

$keywords = ‘%水樹奈々%';

$mysqli = connect($hostname,$db_name,$user_name,$password);

$pages = get_pages($mysqli,$keywords);

foreach($pages as $page) {

   echo “<pre>”;

   var_dump($page);

   echo “</pre>”;

   echo “<hr />”;

}

exit;

function connect($hostname,$db_name,$user_name,$password) {

   $mysqli = new mysqli($hostname,$user_name,$password,$db_name);

   if (mysqli_connect_errno()) {

   printf(“Connect failed: %s\n”, mysqli_connect_error());

   exit();

   }

   return $mysqli;

}

function get_pages($mysqli,$keywords) {

   $sql = “SELECT page_id FROM page WHERE page_title like ‘$keywords'”;

   $result = $mysqli->query($sql);

   if(!$result) {

   $pages = array(0=>fales);

   return $pages;

   }

   while($row = $result->fetch_row()) {

      $page_id = $row[0];

      $text_id = get_text_id($mysqli,$page_id);

      $text_body = get_text_body($mysqli,$text_id);

      $pages[] = $text_body;

   }

   return $pages;

}

function get_text_id($mysqli,$page_id) {

   $sql = “SELECT rev_text_id FROM revision where rev_page = ‘$page_id'”;

   $result = $mysqli->query($sql);

   $row = $result->fetch_row();

   $text_id = $row[0];

   return $text_id;

}

function get_text_body($mysqli,$text_id) {

   $sql = “SELECT old_text FROM text where old_id = ‘$text_id'”;

   $result = $mysqli->query($sql);

   $row = $result->fetch_row();

   $text_body = $row[0];

   return $text_body;

}

?>

【サンプルプログラムダウンロード】

mwiki.php.zip

※注意

表示が文字化けするときは、表示の文字コードをUTF-8にしてください。

関連記事

投稿者:

ともゆき@zubapita

ともゆき@zubapita

作ったモノ 雑誌:月刊アスキー(デスク)、アスキー.PC(副編集長)、インターネットアスキー(編集長)、アスキーPCエクスプローラー(編集長) Webサイト:東京グルメ/ライブドアグルメ、映画を語ろう、本が好き 著書:「Twitter 使いこなし術」「facebook 使いこなし術」 最近は、株式会社ブックウォーカーにて、「BWインディーズ」をやってます。

“WikipediaのダンプデータをDBに投入する” への3件のフィードバック

  1. wikiデータをMySQLに投入する為、参考にさせていただきました。
    ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>