Wikipediaのコンテンツを活用して自前のアプリケーションを書くために、今回Javaで処理する方法を調べました。
まず下準備として、以下のWikimediaのダウンロードページからコンテンツを入手します。
XML,SQL,StaticHTMLの形式が選択できますが、今回は、XMLデータをダウンロードしてそれを活用することにします。
StaticHTMLは便利そうですが、データが古いのと、HTML中にこちらが意図しない情報も含まれていると取り除くのが面倒です。
XMLであれば、直接wiki textで書かれたコンテンツデータを入手できるので、このwiki textをこちらの都合のよいように変換して使うことができます。
Wikimediaのサイトから入手した、jawiki-20081127-pages-articles.xml.bz2を用意します。
XMLをパースして、該当部分を抜き出していきます。(javac 1.6.0_04 を使用しています。)
Main.java,WikidataHandler.java,WikidataHandlerImpl.java を コンパイルした上で、以下のように使います。
$ bzcat jawiki-20081127-pages-articles.xml.bz2 | java Main
結果はコンソールに標準出力されます。
取り出したデータを活用するには、Main.java内のWikidataHandler の cut() メソッドの実装を適切に書きかえます。
import java.io.InputStreamReader;
import java.io.Reader;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class Main {
public static void main(String[] args) {
Reader reader=null;
try{
reader=new InputStreamReader( System.in,"UTF-8" );
XMLReader r=XMLReaderFactory.createXMLReader();
WikidataHandlerImpl handler=new WikidataHandlerImpl(){
@Override
public void cut(int count, long id, String title, String text) {
System.out.println(count);
System.out.println(id);
System.out.println(title);
//System.out.println(text);
}
};
r.setContentHandler(handler);
InputSource is=new InputSource(reader);
r.parse(is);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
try{
reader.close();
}
catch(Exception ex){}
}
}
}
標準入力から得たXMLデータをパースし、Wikipediaの記事を取り出したらcut()メソッドで受け取ります。
interface WikidataHandler {
void cut(int count,long id,String title,String text);
void stop();
}
取り出したデータを受け取るインタフェース。
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
abstract class WikidataHandlerImpl extends DefaultHandler implements WikidataHandler{
static final String[] SKIPWORDS=new String[]{"Wikipedia:","Template:","Category:","画像:"};
static private boolean isSkip(String title){
if(title==null){
return false;
}
for(int i=0; i<SKIPWORDS.length; i++){
String word=SKIPWORDS[i];
if( title.startsWith(word) ){
return true;
}
}
return false;
}
private int currentCount;
private String currentTitle;
private StringBuffer currentText;
private long currentPageId;
private boolean isPage;
private boolean isTitle;
private boolean isText;
private boolean isId;
private boolean isRevision;
private boolean skip;
@Override
public void startElement(String arg0, String arg1, String tagName, Attributes arg3) throws SAXException {
if(pleaseStop){
throw new SAXException("canceled");
//return ;
}
if( tagName.equals("page") ){
isPage=true;
//init
currentPageId=0;
currentTitle="";
currentText=new StringBuffer();
skip=false;
}
if( tagName.equals("title") ){
isTitle=true;
}
if( tagName.equals("id") ){
if(isRevision==false)
isId=true;
}
if( tagName.equals("text") ){
isText=true;
}
if( tagName.equals("revision") ){
isRevision=true;
}
}
@Override
public void endElement(String uri, String localName, String tagName) throws SAXException {
if(pleaseStop)
return ;
if( tagName.equals("page") ){
isPage=false;
if(skip==false){
cut(currentCount,currentPageId,currentTitle,currentText.toString());
currentCount++;
}
}
if( tagName.equals("text") ){
isText=false;
}
if( tagName.equals("revision") ){
isRevision=false;
}
}
@Override
public void characters(char[] ch, int start, int len) throws SAXException {
if(pleaseStop)
return ;
if( isPage && isId && isRevision==false ){
//save current pageId
String id=new String(ch,start,len);
currentPageId=new Long(id).longValue();
isId=false;
}
if(isTitle){
currentTitle=new String(ch,start,len);
skip=isSkip(currentTitle);
isTitle=false;
}
if(isText){
if(skip==false){
String str=new String(ch,start,len);
currentText.append(str);
}
}
}
private boolean pleaseStop;
@Override
public void stop(){
pleaseStop=true;
}
}
パースしたXMLデータの実際の処理をします。
MindBoard は 直観的な操作で簡単にマインドマップを描くことができる Android タブレット用アプリです。