niiyan's blog

niiyanの個人ブログ。

Google App Engine SDK 1.0.2 でクエリ文字列を含む URL のデータが取得できない件(解決済)

注: この問題は、Google App Engine SDK バージョン 1.1.0 で修正済みです。

Google App Engine SDK が 1.0.2 にバージョンアップしたので、さっそくインストールしてみました。念のため、1.0.1 をアンインストールしてから、1.0.2 をインストールしました。

ところが、試しに動かしてみると、検索結果がつねに 0 になったり、商品情報なしになります。そこで、簡略化したスクリプトを使って、ちゃんとデータが取得できているのか確認してみました。

確認用のスクリプト

# -*- coding: utf-8 -*-

# モジュールのインポート
import wsgiref.handlers
from google.appengine.ext import webapp

# Google App Engine ハンドラ
class Fetch(webapp.RequestHandler):
    def get(self):
        # Amazon ECS の URL
        request_url = 'http://ecs.amazonaws.jp/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=(以下略)'
        # Google AppEngine urlfetch
        from google.appengine.api import urlfetch
        xml_data = urlfetch.fetch(request_url).content
        # 出力
        self.response.headers['Content-Type'] = 'application/xml'
        self.response.out.write(xml_data)

# main
def main():
    application = webapp.WSGIApplication(
                                        [('/', Fetch)],
                                        debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()

取得した XML 形式のデータをそのままブラウザに表示するだけのものです(Amazon ECS の URL は省略してありますので、そのままでは動きません)。

結果

すると、

リクエストには、Serviceパラメータが含まれていません。リクエストに Serviceパラメータを追加し、再度リクエストを実行してください。

というエラーメッセージが返ってきました。Amazon.com の場合は、

Your request is missing the Service parameter. Please add the Service parameter to your request and retry.

でした。

Service パラメータは、Amazon ECS の URL の「Service=AWSECommerceService」の部分でちゃんと指定してあります。にもかかわらず、このパラメータが含まれていないということは、「urlfetch.fetch()」に渡した後に URL の文字列が正しく処理されていないのでしょうか。

ちなみに、すべての XML データが取得できないかというとそうでもないようです。Amazon 以外のものもいくつか試してみましたが、たとえば私のブログの RSShttp://feeds.feedburner.com/niiyan)は上のスクリプトで取得することができました。しかし、はてなブックマーク最近の人気エントリーhttp://b.hatena.ne.jp/hotentry?mode=rss)はダメでした。

素人考えで「クエリ文字列を含む URL の処理に何か問題があるのだろうか」と思ったりもしましたが、試した数が少なく、また問題箇所を突き止めたわけでもないので何とも言えません。もうちょっと調べて見るつもりではいますが、これ以上は Python に詳しくないと無理かもしれません。

まとめ

とりあえず、私が試した範囲でわかったことや気づいたことを、最後にまとめておきます。

  • Google App EngineSDK を使わずに、Python だけ(urllib とか)でスクリプトを組むと、ECS のデータは取得できる(スクリプト自体には問題がない?)。
  • Google App EngineSDK のバージョンを1.0.1 に戻したら、意図したとおりに動作した。
    • 1.0.2 のアンインストールでいくつかファイルが残っていたので、いったん削除してから 1.0.1 を入れ直している。
  • オンラインの Google App Engine に置いてあるものは、今のところ、動作しているらしい。
  • 取得できない URL と取得できる URL がある。

追記(2008-05-12)

Issue 341 - googleappengine - Google Code

Google Code の Issue Tracker に私と同じ症状と思われる報告があがっていました。現時点では、まだコメントなどはついていません。

一方、コメントをいただいた mattn さんによれば、1.0.2 でも問題なく取得出来たそうです。

追記(2008-05-15)

修正パッチ

Issue 341 - googleappengine - Google Code にて、jkester さんがパッチを提供されています。「`google_appengine/google/appengine/api/urlfetch_stub.py`」に対するパッチです。

urlfetch_stub.py を見てみたところ、70 行目と 118 行目で urlparse を使って、パス(path)やクエリ(query)などを取り出していますが、このあとこの query はどこにも使われていないように見えます。jkester さんのパッチは、この query が空でない場合には、path の後ろに ? と query を追加するというもののようです。

実際にパッチを適用してみたところ、Amazon ECS のようにクエリ文字列を含む URL からデータを取得できるようになりました。とりあえず、ローカルで開発する分にはこれで何とかなりそうです。ただ、オンライン(App Engine)上のアプリが動かなくなるのでは、という不安は残りますが……。

ちなみにパッチの適用の仕方については、patch/diff Tips が参考になります。今回のパッチの場合、そんなに量が多くないので、該当部分を手動で修正してもいいと思います(念のため、オリジナルのバックアップを取っておいたほうがいいでしょう)。

改題

初出時のタイトルは「Google App Engine SDK 1.0.2 で Amazon ECS のデータが取得できない件」でしたが、クエリ文字列を含む URL が関係する問題のようなので、記事タイトルを「Google App Engine SDK 1.0.2 でクエリ文字列を含む URL のデータが取得できない件」に改めました。

追記(2008-05-30)

28 日付けでリリースされたGoogle App Engine SDK バージョン 1.1.0 で、この問題は修正されました。

Issue 341 - googleappengine - Google Code

Comment 13 by ryanb+ap...@google.com, Today (6 hours ago)

hi all! thanks for the report, and sorry for the trouble. this should be fixed in 1.1.0.



コメント(過去分)

※コメントがインポートできなかったため、旧ブログ時代にいただいたコメントについては、記事の末尾に再掲載する形を取らせていただいています。

No title

報告だけで申し訳ないですが...
1.0.2にあげてみましたいが私は問題なく取得出来ました。

Posted by mattn at 2008/05/12 (Mon) 13:00:28

報告ありがとうございます。

いえいえ、問題なく動作しておられると聞いて、少し安心しました。
さきほど追記したのですが、他にも私と同じ症状の方がいらっしゃるようなので、私だけの問題というわけではないとは思うのですが……。
とりあえず、もう少し調べてみます。

Posted by にーやん at 2008/05/12 (Mon) 23:46:38

SDK 1.0.2( Windows)

Windows SDK - Issues importing .pyd files」
http://code.google.com/p/googleappengine/issues/detail?id=222
この不具合のために

http://code.google.com/p/google-app-engine-samples/downloads/list
にある 
muvmuv_20080409.tar.gz の /build が
SDK 1.0.1 ( Windows) では動作しませんでした。
mattn さんのプログラムを参考にした flickr の検索OK

SDK 1.0.2( Windows) にしたところ
muvmuv_20080409.tar.gz の /build --> OK
mattn さんのプログラムを参考にした flickr の検索 --> NG

教えていただいた、
Issue 341
URL Fetch API should pass querystring in HTTP GET
http://code.google.com/p/googleappengine/issues/detail?id=341
を適用し、
mattn さんのプログラムを参考にした flickr の検索 --> OK
でした。

Posted by kw at 2008/05/15 (Thu) 13:14:48

Re: SDK 1.0.2( Windows)

muvmuv_20080409.tar.gz のサンプルを少し見てみました。
urlfetch.fetch() が使われているところは 2 箇所ありますが、いずれもクエリ文字列を含まない URL が引数として渡されているようです。
ですから、Issue 341 はあてはまらず、1.0.2 でも OK だったということでしょうか。

Posted by にーやん at 2008/05/15 (Thu) 23:31:31

Re:Re: SDK 1.0.2( Windows)

>ですから、Issue 341 はあてはまらず、1.0.2 でも OK だったということでしょうか。
はい、muvmuv については、素直に 1.0.2 にしたことで、 /build が
動作するようになりました。 (Issue 341 の対応は必要なし)

Posted by kw at 2008/05/16 (Fri) 09:47:17