読者です 読者をやめる 読者になる 読者になる

Google App EngineでのXMLを使った処理

どうやっているか

XMLから情報を得たいときには

  1. XML文字列そのものを取得
  2. その文字列をパースする(DOMを取得)
  3. DOMから指定したタグの情報を取得する

という流れになると思うんですが、Google App EngineXMLのパースをどうやってやればいいかちょっと悩んだので書いておきます。


まず1.はgoogle.appengine.apiのurlfetchを使えばOKです。
問題は2と3なんですが、今回はxml.domのminidomを使ってみました。
本当はElementTreeというPythonXMLパーサライブラリを使うと
もっと柔軟にかつ楽にXMLを処理できるのですが、Google App Engineではデフォルトで使えないのでやめました。*1


minidomではparseString()メソッドでXMLをパースできます。
そしてそのDOMのgetElementsByTagName("タグ名")でタグ名のタグのNode配列が取得できます。

xml = urlfetch.fetch(url).content
dom = minidom.parseString(xml)
nodes = dom.getElementsByTagName("tag")

それぞれのNodeからタグ内の文字を取得するときは、

for node in nodes:
  print node.childNodes[0].data

のようにすると取得できます。


ちなみに上のニコニコ動画のタグを取得するサンプルはGoogle App Engineを使って書きました。
http://voidy21.appspot.com/nicotag_example/index.html
ニコニコ動画XML情報をJSON形式で返して、jQueryを使って表示しました。
サーバ(python)のソース

# -*- coding: utf-8 -*-
import wsgiref.handlers
import cgi
from xml.dom import minidom 
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.api import urlfetch

class GetNicoTags(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'application/json'
    self.response.headers['charset'] = 'UTF-8'
    
    callback = cgi.escape(self.request.get('callback'))
    video_id = cgi.escape(self.request.get('video_id'))
    url = 'http://www.nicovideo.jp/api/getthumbinfo/%s' % (video_id)
  
    xml = urlfetch.fetch(url).content
    dom = minidom.parseString(xml)
    tags = dom.getElementsByTagName("tag")
    
    nicotags = {"tags":[]}
    append_nico = nicotags["tags"].append
    for tag in tags:
      append_nico({"tag":tag.childNodes[0].data})
    self.response.out.write("%s(%s)" % (callback, simplejson.dumps(nicotags, ensure_ascii=False)))

application = webapp.WSGIApplication([
  ('/nicotag', GetNicoTags),
], debug=False)

def main():
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()

*1:使いたいときは、elementtreeディレクトリを作ってPyWrapperのSimpleXMLTreeBuilder.pyElementTree.pyを落としてきて、__init__.pyという名前の空のファイルを作成しておく。そして[http://mattn.kaoriya.net/software/lang/python/20080424212547.htm:title]を参考にしてElementTree.pyを書き換える。