質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
JSONP

JSONP(JSON with padding)は、JSONを使用した関数呼び出しのための仕組み。クロスドメインでのデータの受け渡しが可能です。JavaScriptからクロスドメインで容易にデータを扱うことができます。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

5392閲覧

GASのAPIへpythonからURLアクセスGet送信し特定のレスポンスを受け取りたい。

dendenmushi

総合スコア98

JSONP

JSONP(JSON with padding)は、JSONを使用した関数呼び出しのための仕組み。クロスドメインでのデータの受け渡しが可能です。JavaScriptからクロスドメインで容易にデータを扱うことができます。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

1グッド

0クリップ

投稿2020/05/23 06:42

編集2020/05/24 02:06

前提・実現したいこと

Google App Scripts でWebAPIを作り、pythonからURLアクセスし、レスポンス(text)を受け取りたい。

参考サイト:https://qiita.com/satto_sann/items/be4177360a0bc3691fdf

現状

URLアクセスすればコード200とレスポンスをブラウザに表示されるようになりました。

サイト紹介のAPIのURL:https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja

イメージ説明

もしくは、Operaブラウザでのアクセス後の表示
イメージ説明

source code

今回python側のJSON受け取りの問題なのですが念のためGAS側も掲載します。

GAS

1function doGet(e) { 2 // リクエストパラメータを取得する 3 var p = e.parameter; 4 // LanguageAppクラスを用いて翻訳を実行 5 var translatedText = LanguageApp.translate(p.text, p.source, p.target); 6 7 // レスポンスボディの作成 8 var body; 9 if (translatedText) { 10 body = { 11 code: 200, 12 text: translatedText 13 }; 14 } else { 15 body = { 16 code: 400, 17 text: "Bad Request" 18 }; 19 } 20 // レスポンスの作成 21 var response = ContentService.createTextOutput(); 22 // Mime TypeをJSONに設定 23 response.setMimeType(ContentService.MimeType.JSON); 24 // JSONテキストをセットする 25 response.setContent(JSON.stringify(body)); 26 27 return response; 28}

python

1import urllib 2import urllib.request 3import pdb 4response = urllib.request.urlopen('https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja') 5 6print('url:', response.geturl()) 7print('code:', response.getcode()) 8print('text:', response.info()['body']) 9print('text3:', response.info()) 10print('text4', response.headers['Content-Type']) 11print('text4', response.headers) 12 13print('text4', response.body['text']) 14print('Content-Type:', response.info()['Content-Type']) 15content = response.read() 16print(content) 17response.close()

発生している問題・エラーメッセージ

しかし、そのままprint表示しますとResponse<200>のみで”こんにちは"のみを返却して利用したいのですが、目当てのものが取得できないでおります。

かなりたくさんの方法でレスポンスからtextの結果のこんにちはを受け取ろうとしましたが、他のものがprint表示されています。

試したこと

python

1import json 2import urlopen 3import pdb 4jsons = urlopen("https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja").read().decode('utf-8').split('\n') 5 6result = [] 7for v in jsons : 8 try: 9 js = json.loads(v) 10 result.append( js['info'] ) 11 except Exception: 12 pass 13pdb.set_trace() 14print(result)

python

1from urllib.request import Request, urlopen 2from urllib.error import URLError 3req = Request("https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja") 4try: 5 response = urlopen(req) 6except URLError as e: 7 if hasattr(e, 'reason'): 8 print('We failed to reach a server.') 9 print('Reason: ', e.reason) 10 elif hasattr(e, 'code'): 11 print('The server couldn\'t fulfill the request.') 12 print('Error code: ', e.code) 13print(response)

python

1import requests 2import json 3 4#GET先URL 5# url = "https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec" 6 7#JSON形式のデータ 8jsonData = { 9 "text": "Hello", 10 "source": "en", 11 "target": "ja" 12} 13 14#GET送信 15response = requests.post( 16 url = "https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec", 17 params = jsonData 18 ) 19 20resDatas = response.json() 21 22print(resDatas)

python

1import execjs 2print(execjs.eval("'red yellow blue'.split(' ')")) 3 4ctx = execjs.compile("""function add(x, y) {return x + y;}""") 5print(ctx.call("add", 1, 2)) 6 7import requests 8get_url_info = requests.get('https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja') 9print(get_url_info) 10 11 12payload = {'text': 'Hello', 'source': 'en', 'target': 'ja'} 13r = requests.get('https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec', params=payload) 14print(r.args['text'])

どのようにすればレスポンスコード200ではなくtextのこんにちはを取得できるのでしょうか。
pythonのHTTPGET時のJSONのパラメータ受け取りについてアドバイス頂けないでしょうか。
よろしくお願い致します。

補足情報(FW/ツールのバージョンなど)

python3.7
windows10 home
GAS

2020/05/24 10:56 追記

GAS側で公開設定しなければレスポンスのContentTypeがJSONにならずデコードエラーになってしまう(API実行後のpython受け取り時)ため、しっかりと公開をしているか再度確認しました。
エラーの際の画面
イメージ説明

対応としてアドバイス頂いたGAS公開設定。
イメージ説明

しかし再度API実行したところ状況変わらずでした。
ひとつ懸念点は、どうやらGASは唯一のデメリットとして反映するまでに時間がかかるとのことでした。でもすぐに反映できたと言われたため私は他に原因があるのでしょうか。

teamikl👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

試したこと、それぞれで別々の問題がありそうです


取り急ぎ (1) について python3.x系と仮定します

  • import 対象と
  • デコードした辞書のキー
# モジュールを直接 urlopen() と呼び出すことはできません # 関数をimportする。 from urllib.request import urlopen

{"code":200, "text": "こんにちは"}

なので、info ではなく

diff

1- result.append( js['info'] ) 2+ result.append( js['text'] )

ブラウザで確認する際の注意点は、
例えばキーを変更した場合、キャッシュの影響がないか確認して下さい。


追記
urlopenの戻り値はファイルとして扱えるオブジェクトなので
json.loadに直接渡すこともできます

python

1import json 2from urllib.request import urlopen 3res = urlopen("https://script.google.com/macros/s/AKfycbzZtvOvf14TaMdRIYzocRcf3mktzGgXvlFvyczo/exec?text=Hello&source=en&target=ja") 4print(json.load(res)["text"])

投稿2020/05/23 07:32

編集2020/05/23 11:32
teamikl

総合スコア8660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dendenmushi

2020/05/23 07:56

本当にありがとうございます。['text']なのですね…
teamikl

2020/05/23 08:03

(3) の方は別の問題みたいです(追ってみてます #GET送信 response = requests.post( <-- POST送信になっている ==== (4) であれば最後の方 # XXX: print(r.args['text']) print(r.json()['text'])
dendenmushi

2020/05/23 10:16

ありがとうございます。①のやり方でHelloなどの単語であればいいのですが、なぜかThis is important.のように空白が混ざるとURLを実行する分にはいいのですが、resultにいい結果がでないですね。どうしてなのか空白除去などを試しているのですが長文だとうまくurlopen実行できないようです。
dendenmushi

2020/05/23 10:35

失礼しました。④で長文大丈夫ですね。ありがとうございました。
teamikl

2020/05/23 11:31 編集

一応、原因は .split('\n') で分割してるからです。 ※訂正 コメント欄だとレイアウト崩れたので、回答に含めます
dendenmushi

2020/05/23 14:59 編集

ここにきておかしな現象が起きました。④のやり方でやっています。 ''' payload = {'text': txt, 'source': 'en', 'target': 'ja'} r = requests.get('https://script.google.com/macros/s/*******/exec ' , params=payload) print(r.json()['text']) ''' 紹介したサイトのAPIURLであればまったくうまくいきます。ありがとうございました。でも私が作ったもの、(参考サイトと同じ方法でGASを作ってます。)で行ったところ、 ''' \lib\json\decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1) ''' というログが出てしまい、うまくいきませんでした。もしかしたらGASの作り方が違うのかもしれません。再考してみます…。 **2020/05/23 23:58 追記 https://intellectual-curiosity.tokyo/2019/11/02/python%E3%81%AErequests%E3%81%A7%E3%80%8Cjson-decoder-jsondecodeerror-expecting-value-line-1-column-1-char-0%E3%80%8D%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E5%8A%9B%E3%81%95%E3%82%8C/ どうやらレスポンスがJSONでないものが(text)帰ってきてるようで、サイトの通りに作ったGASの返却価が違うようでした。
dendenmushi

2020/05/23 15:18

参考サイトのGASのレスポンスはJSON、私が作ったGASのレスポンスは、text/html; charset=UTF-8であることがわかりました。同じコードにも関わらず違いました。作り方で不足している部分があるかもしれないので、そのあたり再度みてみます。
teamikl

2020/05/23 22:26

ログイン画面のHTMLが返ってのかもしれませんね。 GAS側の公開設定はどうなってますか? 権限を全員に公開とするとうまくいきませんか? 自分のみ等の制限した場合、ブラウザ以外からのアクセスには クッキーやセッション等の認証情報が必要になります。
teamikl

2020/05/23 22:58

GAS側の公開設定で、アクセスを制限することで同じ JSONDecodeError と アクセス制限をなくすことで正常に JSON を読み込めるようになるのを確認しました。
dendenmushi

2020/05/24 02:08

引き続きありがとうございます。こちらでも公開設定(本文に追記しました。)をしたのですが、状況かわらずでした。GAS変更はタイムラグがあるようですのでしばらくたってから行う予定ですが、他に原因がありそうな気がしています。
teamikl

2020/05/24 04:24

全ユーザーではないのかな。もう一つそのしたにありませんでした? スクリプトでのアクセスは、ログインがないからユーザ情報もない状態なので。 後、実行者は影響有るかわかりませんが、「自分」で >Users will be asked to authorize the script. と承認を求められるようですが、これもログインしてない状態なので、出来ないはず。 参考までに成功した設定 - Execute the web app: Me - Who has access to the app: Anyone, even anonymous
dendenmushi

2020/05/24 07:53 編集

全ユーザーを選んでました。anonymousの一番下のだったのですね。ありがとうございました。うまくいきました。非常に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問