WikipediaのAPIを使って情報を取得するクラスを書いてみました

先日公開したスコアアタックしりとりもまだ予定のすべての機能が完成したわけではないのですが、最近は次は何作ろうかなということを考えて様々なサービスのAPIを調べています。

今回WikipediaAPIに接続して情報を取得するクラスを書いてみました。
Wikipediaの、と書きましたがWikipediaに使われているソフトであるMediawikiを使用したサイトであればAPIは共通なのでWikipedia専用というわけではありません。

Wikipedia APIの仕様についてはMediaWiki API ヘルプ - WikipediaなどAPIに引数なしでアクセスすることで見ることができます。
このクラスではURLのパラメータに当たる部分を辞書で引数に渡しインスタンスを作成すると、すぐにAPIに接続し受け取ったレスポンスをDOM化します。DOMはインスタンスのdomというプロパティからアクセスします。
formatをXML以外にした場合はDOM化はされずrawdataプロパティがレスポンスをそのまま参照します。

# coding: utf-8

import urllib
import urllib2
from xml.dom.minidom import parse as parseXML

URL = 'http://ja.wikipedia.org/w/api.php?'
BASIC_PARAMETERS = {'action': 'query',
                    'format': 'xml'}


class WikiHandler(object):
    def __init__(self, parameters, titles=None, url=URL):
        self._url = url if url.endswith('?') else url + '?'

        self._parameters = {}
        self._parameters.update(BASIC_PARAMETERS)
        self._parameters.update(parameters)

        if titles:
            self._parameters['titles'] = titles

        self.rawdata = self._urlfetch(self._parameters)

        if self._parameters['format'] == 'xml':
            self.dom = parseXML(self.rawdata)
            print 'DOM ready.'

    def _urlfetch(self, parameters):
        parameters_list = []

        for key, val in parameters.items():
            if isinstance(val, basestring):
                val = val.encode('utf-8')
            else:
                val = str(val)

            val = urllib.quote(val)
            parameters_list.append('='.join([key, val]))

        url = self._url + '&'.join(parameters_list)

        print 'Accessing...\n', url

        return urllib2.urlopen(url, timeout=20)

日本語版Wikipediaから「プログラミング言語」というカテゴリに属している記事とサブカテゴリの一覧を取得して表示するコードは下のようになります。

def main():
    parameters = {'list': 'categorymembers',
                  'cmlimit': 500,
                  'cmtitle': u'Category:プログラミング言語'}

    page = WikiHandler(parameters)

    elelist = page.dom.getElementsByTagName('cm')

    print elelist.length # 要素数

    for ele in elelist:
        print ele.getAttribute('title')


if __name__ == '__main__':
    main()

結果は下のようになります。(長いので後半は省略)

Accessing...
http://ja.wikipedia.org/w/api.php?action=query&cmtitle=Category%3A%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E&cmlimit=500&list=categorymembers&format=xml
DOM ready.
278
プログラミング言語
Template:ProgLangCompare
プログラミング言語一覧
プログラミング言語の比較
プログラミング言語年表
4GL
A+
A-0 System
ABAP
ABC (プログラミング言語)
Ada
ALGOL
APL
Autocode
AutoIt
AWK
B言語
BASIC

以下省略