WikipediaのダンプデータをDBに投入する
3月 2nd, 2009
最近、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のダウンロード
ダウンロードしたソースファイルを解凍し、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ダンプデータをダウンロードする。
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 revisionのid
rev_page このrevisionのpage.page_id
rev_text_id このrevisionのID = text.old_id
textテーブル
old_id textのid
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;
}
?>
【サンプルプログラムダウンロード】
※注意
表示が文字化けするときは、表示の文字コードをUTF-8にしてください。
関連記事
- Wikipedia API(検索&パース)を作りました
- QuictyによるPHP Webアプリの超高速開発-(2)Quictyアプリの基本構造
- phpPgAdminの導入
- XAMPP for Windows-(1)インストール
- MacでWeb開発-(7) XAMPP for Macでブログを運営(WordPress)
カテゴリー: ウェブ開発/設定









[...] ただし、先日WikipediaのダンプデータをDBに投入する で紹介したように、Wikipediaはサーバから叩けるAPIを提供していない。不定期にダンプデータが提供されているので、それを自分のサ [...]
wikiデータをMySQLに投入する為、参考にさせていただきました。
ありがとうございました。