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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Python

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

API

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

Q&A

1回答

1495閲覧

pythonからGASに移植したい

SYSYSYSYSYSY

総合スコア8

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Python

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

API

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

0グッド

1クリップ

投稿2021/11/19 09:11

編集2021/11/20 01:32

以下のpythonコードをGASに翻訳したいのですが、どのようにしたらよいでしょうか?
よろしくお願いします。
これまでもGASはそこそこ書いてきてるのですが、掲載したコードではbad requestのエラーがでます。
どこか修正できるところがあるでしょうか?
ご教示よろしくお願いいたします。

python

1import requests 2 3url = "http://myapi/internal/ocr/requestid/ng" 4 5payload={} 6headers = { 7 'X-Authorization': 'abcdefghijklmn' 8} 9 10response = requests.request("POST", url, headers=headers, data=payload) 11 12print(response.text)

GAS

1function sending(yesorno, requestId) { 2 var requestId = "*******************" 3 var STAGING_KEY = "abcdefghijklmn" 4 5 var url = url = "http://myapi/internal/ocr/"+requestId+"/ng" 6 7 var data = {} 8 var options = { 9 'muteHttpExceptions': true, 10 'method': 'post', 11 'payload': JSON.stringify(data), 12 'headers': { 13 'X-Authorization': STAGING_KEY 14 } 15 }; 16 17 //Error processing 18 try { 19 var response = JSON.parse(UrlFetchApp.fetch(url, options)); 20 if (response && response["id"]) { 21 return 'sent'; 22 } else { 23 //reportError("Invalid response: " + JSON.stringify(response)); 24 //return 'error'; 25 Logger.log('error') 26 } 27 } catch (e) { 28 //reportError(e.toString()); 29 //return 'error'; 30 Logger.log('error') 31 } 32} 33

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

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

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

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

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

1T2R3M4

2021/11/19 09:23

まずGASを学習しましょう。
papinianus

2021/11/25 17:26

社内用の API だとしたら origin みてるんじゃないですかね。 それよりも gas にすることのメリットというか、gas にすることで解決したい課題を共有いただいたほうがよいような気がします。
SYSYSYSYSYSY

2021/11/29 04:01

ご指摘ありがとうございます。スプレッドシート上でステータスを変更するとapiにpostされて、post先のステータスも変更されるというものを作ろうとしておりました。 python、curlで試すとうまくいくのですが、GASだけ通らないので、GAS特有の理由かコードミスと思っておりました。説明になってるといいのですが。 何かアイデアがあればよろしくお願いします。
guest

回答1

0

GASのUrlfetchAppはリクエスト送信時に特有のUserAgentを付け加えます。

サーバーは、そのUserAgentを判別してアクセスを弾いている可能性があります。

なお、このUserAgentは変更できません。(ヘッダに任意のUser-Agentを付け加えても元のUser-Agentに上書きされます)


追記

どのような内容のrequestを行ったかを知りたいとき、https://httpbin.org/ というサイトを利用することができます。

今回のように、post内容を調べたい場合は、https://httpbin.org/post というエンドポイントに対してpostすると、自分がpostした内容がそのままレスポンスとして返ってきます。

質問文のpost内容を調べてみました。
調べるためのソースコードは以下です。(単純に、apiエンドポイントを "https://httpbin.org/post"に変えて、responseをダンプしているだけです)

python

python

1import requests 2 3url = "https://httpbin.org/post" 4 5payload={} 6headers = { 7 'X-Authorization': 'abcdefghijklmn' 8} 9 10response = requests.request("POST", url, headers=headers, data=payload) 11 12 13print(response.text)

GAS

js

1function sending(yesorno, requestId) { 2 var requestId = "*******************" 3 var STAGING_KEY = "abcdefghijklmn" 4 5 // var url = url = "http://myapi/internal/ocr/"+requestId+"/ng" 6 var url = "https://httpbin.org/post" 7 var data = {} 8 var options = { 9 'muteHttpExceptions': true, 10 'method': 'post', 11 'payload': JSON.stringify(data), 12 'headers': { 13 'X-Authorization': STAGING_KEY 14 } 15 }; 16 17 //Error processing 18 try { 19 var response = JSON.parse(UrlFetchApp.fetch(url, options)); 20 Logger.log(JSON.stringify(response,undefined,1)) 21 if (response && response["id"]) { 22 return 'sent'; 23 } else { 24 //reportError("Invalid response: " + JSON.stringify(response)); 25 //return 'error'; 26 Logger.log('error') 27 } 28 } catch (e) { 29 //reportError(e.toString()); 30 //return 'error'; 31 Logger.log('error') 32 } 33}

<結果比較>
pythonのレスポンス

{ "args": {}, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "python-requests/2.12.4", "X-Amzn-Trace-Id": "Root=*-******-***************", "X-Authorization": "abcdefghijklmn" }, "json": null, "origin": "***.***.***.***", "url": "https://httpbin.org/post" }

GASのレスポンス

diff

1{ 2 "args": {}, 3 "data": "", 4 "files": {}, 5+"form": { 6+ "{}": "" 7+}, 8 "headers": { 9 "Accept-Encoding": "gzip, deflate, br", 10+ "Content-Length": "2", 11 "Content-Type": "application/x-www-form-urlencoded", 12 "Host": "httpbin.org", 13 "User-Agent": "Mozilla/5.0 (compatible; Google-Apps-Script; beanserver; +https://script.google.com; id: *****-********************)", 14 "X-Amzn-Trace-Id": "Root=*-******-***************", 15 "X-Authorization": "abcdefghijklmn" 16 }, 17 "json": null, 18+"origin": "****:****:****:****:****:****:****:****, ***.***.***.***", 19 "url": "https://httpbin.org/post" 20}

比較した結果、色付き(先頭行が+の行)が主な相違点です。
まとめると

  1. form(pythonは {}だが、GASは {"{}":""}
  2. Content-Length (python は0、GASは2)
  3. origin (pythonはIPv4、GASはIPv6)
  4. User-Agent(前述)

となっています。

おそらく、2は1に依存しています。
もし違いが出るとするならば、formのところと推測されます。

formに関して、GASの方をpythonと同じ形にするには、下記のように、payloadを削除すればよいことがわかりました。

GAS改

js

1function sending(yesorno, requestId) { 2 var requestId = "*******************" 3 var STAGING_KEY = "abcdefghijklmn" 4 5 // var url = url = "http://myapi/internal/ocr/"+requestId+"/ng" 6 var url = "https://httpbin.org/post" 7 var data = {} 8 var options = { 9 'muteHttpExceptions': true, 10 'method': 'post', 11 // 'payload': JSON.stringify(data), //削除 12 'headers': { 13 'X-Authorization': STAGING_KEY 14 } 15 }; 16 17 //Error processing 18 try { 19 var response = JSON.parse(UrlFetchApp.fetch(url, options)); 20 Logger.log(JSON.stringify(response,undefined,1)) 21 if (response && response["id"]) { 22 return 'sent'; 23 } else { 24 //reportError("Invalid response: " + JSON.stringify(response)); 25 //return 'error'; 26 Logger.log('error') 27 } 28 } catch (e) { 29 //reportError(e.toString()); 30 //return 'error'; 31 Logger.log('error') 32 } 33}

上記のように「payloadなし」で試してみてはいかがでしょうか。

投稿2021/11/20 04:43

編集2021/11/22 13:05
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

SYSYSYSYSYSY

2021/11/20 05:32

丁寧なご説明ありがとうございます! カード自体には問題なさそうでしょうか?
退会済みユーザー

退会済みユーザー

2021/11/20 05:41 編集

サーバーを明らかにされていませんので何とも言えません。 httpbinというサイトで、自分がどのようなリクエストをpostしたのか調べられますので、 (正常に通る)pythonのpostと(Bad Requestになる)gasのpostのどこが違うのか、確かめてみてはいかがでしょうか。 https://qiita.com/sameyasu/items/adacceb8a1bee893599b ただし、httpbinはあくまでリクエスト内容を確認できるだけです。 サーバー依存の処理がある場合は、たとえhttpbin上で同一のpostであっても異なる挙動を示す場合が有りますので 完全ではありません。 具体的なapiエンドポイントを非公開にしている以上、誰もつっこんだ回答はできないと思います。 使いたいapiサービスのヘルプ等に問い合わせてみることをお勧めします。
SYSYSYSYSYSY

2021/11/22 00:17

丁寧なご返答ありがとうございます。 社内開発したAPIを使用しており、RPAを秘密で進めているため、開発者に直接仕様をきくことができず、このような曖昧な質問になってしまいました。 ただpythonでは通るので、可能性としてまずGASのコードに間違いがないかをチェックして頂きたかったです。 もしコードに間違いがないのであれば、サーバではじかれている可能性が高いと思います。
退会済みユーザー

退会済みユーザー

2021/11/22 13:04

追記しました。GASについてはpayloadなしで試してみて下さい。
SYSYSYSYSYSY

2021/11/24 02:53

追記ありがとうございます! postmanで成功する場合のContent-Lengthが0だったため、payloadを削除して試してみましたが、やはりエラーが出てしまいます。前述いただいた通り、UserAgentの問題でしょうか?? 色々試していただいて、本当にありがとうございます!!
退会済みユーザー

退会済みユーザー

2021/11/24 03:45

ご記載の通り、おそらくUserAgentの問題である可能性が高いと思います。
SYSYSYSYSYSY

2021/11/25 00:58

そうですね、色々教えていただき、本当に勉強になりました! 今一度、ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問