Google App Engine SDK: XML データの取得、パース、結果表示まで
ちょうどあまびきを 1 から作り直そうと考えていたところだったので、Google App Engine でやってみることにした。前回、検索フォームの設置まで行ったので、実際に Amazon ECS にリクエストして、返ってきたデータをパース、さらに画像を表示するまでをやってみた。
まず Google App Engine SDK と組み合わせないで、Amazon から XML データを取ってきてパースするというところまでは何とかできた。でも、いざ Google App Engine と組み合わせると動かない。
urllib でエラー
まず、urllib モジュールの urlopen を使って Amazon にリクエストしようとしたら、
AttributeError: 'module' object has no attribute 'unlink'
というエラーが出てうまく行かなかった。urllib2 でもやってみたが、別のエラーが出てうまく行かない。
代わりに Google App Engine の URL Fetch API を使うことにした。
ElementTree でもエラー
Google App Engine には Python 2.5.x が入っているということなので、ElementTree モジュールを使って XML をパースしようと考えた。が、いざ Google App Engine 上(ローカル)で実行してみると、
ImportError: No module named expat; use SimpleXMLTreeBuilder instead
というエラーが出た。
SimpleXMLTreeBulider で検索すると、Big Sky :: Google App EngineでXMLをパースする方法(python版WebService::Simpleを使ってflickr画像検索を作る) に行き当たる。だが私のレベルでは、PyWrapper が一体何で、どうすればいいのかわからず……。
だが PyWrapper のサイト内にある SimpleXMLTreeBuilder.py と ElementTree.py を落としてきて使ってみると、うまく XML がパースできるようになった。とりあえずよしとする。
なお、SimpleXMLTreeBuilder の使い方については、上述の Big Sky の記事にある webSimple.py を参考にさせていただいた。感謝。
結果の表示

とりあえず画像の表示まで。
関連記事
Google App Engine SDK: 検索フォームを作ってみる
少し戻って Handling Forms With webapp - Google App Engine - Google Code を読みながら、簡単な検索フォームを作ってみる。
基本的には、ほぼ Handling Forms With webapp - Google App Engine - Google Code のまま。ただし、すでにテンプレートの使用を勉強済みだったので、検索結果の表示には別にテンプレートを用意した。
1. result.html の作成
検索結果表示用のテンプレートを作成。result.html とする。
2. cgi モジュールのインポート
import cgi
文字列のエスケープに使用。
3. 検索用のクラスを作成
class Search(webapp.RequestHandler):
def post(self):
# クエリを取得してエスケープ
query = cgi.escape(self.request.get('q'))
# テンプレートに渡す値を更新
template_values.update({
'query': query
})
# パスの結合
path = os.path.join(os.path.dirname(__file__), 'result.html')
# テンプレートを元に画面に書き出す
self.response.out.write(template.render(path, template_values))
4. Search ハンドラの URL マッピングを追加
webapp.WSGIApplication に Search ハンドラの URL マッピングを追加:
def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/search', Search)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
5. 実行

とりあえず、検索フォームに入力した文字列を取り出して表示するところまで。
関連記事
Google App Engine SDK: CSS や JS などの静的ファイルを利用する
CSS や JS(JavaScript)などの静的な外部ファイルを利用するには、まず app.yaml の handlers セクションで静的ファイルを含むディレクトリのパスなどを定義する必要があるらしい。Using Static Files - Google App Engine - Google Code を参考にやってみた。
CSS ファイルの利用
今回は外部 CSS ファイルで試してみました。
1. app.yaml の変更
handlers:
- url: /css
static_dir: css
- url: /.*
script: helloworld.py
上から順にマッチするかテストされるので、/css から始まる URL にリクエストがあると、css ディレクトリにあるファイルから適当なファイルを探すようになるらしい。……が、
<class 'google.appengine.tools.dev_appserver.InvalidAppConfigError'>: regex invalid: unbalanced parenthesis
というエラーが出てうまくいきませんでした。代わりに次のようにしてみたら動いた:
- url: /css/(.*\.css)
static_files: css/\1
upload: css/(.*\.css)
app.yaml の書き方については、Configuring an App - Google App Engine - Google Code を参照。
2. css の作成
外部スタイルシートを作成して、css ディレクトリに保存。
/* 例です */
body {
background: #eaeaea;
color: #333333;
}
#title {
color: #333399;
font-style: italic;
}
3. テンプレートの変更
テンプレートファイルの index.html の head 要素に CSS へのリンクを追加。
<head>
<link type="text/css" rel="stylesheet" href="/css/test.css" />
</head>
こんな感じで JavaScript や Flash なんかも利用可能になるらしいです。
メモ
MIME タイプ
MIME タイプは基本的に拡張子を元に決定される。追加オプションで変更することも可能。
参考: Configuring an App - Google App Engine - Google Code
関連記事
Google App Engine SDK: テンプレートの使用
チュートリアルでは、フォーム画面の作成、データの格納へと移るが、飛ばして先に進む。
webapp フレームワークには、Django のテンプレートエンジンが含まれているらしい。と言っても、その Django がよくわからないのだが、とりあえず Using Templates - Google App Engine - Google Code を参考にやってみる。Django については、機会があれば勉強するということで……。
1. template のインポート
helloworld.py に次の 2 行を追加する:
import os
from google.appengine.ext.webapp import template
2 行目が template モジュールの読み込み。1 行目で os モジュールがインポートされているが、パスの結合に必要みたい。この場合、os.path だけでもいいような気がするが、気にせず続ける。
2. index.html の作成
チュートリアルの例をいきなり理解するのは無理だったので、簡単なものにしてみた。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{{ title }}</title>
</head>
<body>
<p><span id="title">{{ title }}</span></p>
</body>
</html>
{{ title }} という部分が置換される部分。index.html という名前で保存。名前は別に index.html じゃなくてもいいかもしれない。
3. MainPage クラスの修正
self.response.out.write('<html><body><p>こんにちは、webapp の世界!</p></body></html>')
ここを次のように修正する:
template_values = {
'title': 'こんにちは、Google App Engine!'
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
リロードしてみると、ちゃんと {{ title }} の部分が置換されていた。Using Templates - Google App Engine - Google Code を見ると、if 文や for 文なんかも使えるようなので、あとでまたやってみる。とりあえず、ここまで。
関連記事
Google App Engine SDK: webapp フレームワーク
Using the webapp Framework - Google App Engine - Google Code から、webapp フレームワークという WSGI 互換のフレームワークを使った作業に移る。
Google App Engine では、Django も使えるらしいので、この機会に勉強してみようかとも思っていたけど、webapp についてもちょっと読んでみる。The webapp Framework - Google App Engine - Google Code に webapp フレームワークのドキュメントがある。
以下、メモ。
out プロパティ
via Building the Response - Google App Engine - Google Code
self.response.out.write("<html><body><p>Hi there!</p></body></html>")
out プロパティは、レスポンスのボディを書き出すために使用されるファイル風のオブジェクト
Content-Type ヘッダ
via Building the Response - Google App Engine - Google Code
デフォルトは、「text/html; charset=utf-8」
debug モード
via Running the Application - Google App Engine - Google Code
application = webapp.WSGIApplication(
[('/', MainPage)],
debug=True)
「debug=True」でデバッグモード。例外が起きたときに、webapp にブラウザに stack trace を表示させるようにする。デフォルトでは、エラー発生時に HTTP 500 エラーを返す。
Google アカウントとの統合
via Using the Users Service - Google App Engine - Google Code
Google アカウントを使ってサインインさせたり、サインインしていないなら認証画面にリダイレクトしたりできるらしい。個人的に今のところ必要なさそうなので、サラッと読み飛ばす。
詳細は、The Users API - Google App Engine - Google Code



