web-dev-qa-db-ja.com

Pythonリクエストライブラリを使用して投稿リクエストを行う方法は?

Postmanで以下のフィルターを使用して、Web APIでPOSTリクエストを作成していますが、単純なPOSTでリクエストをPythonリクエストライブラリで。

最初に、POSTこのURLにリクエストを送信しています( http://10.61.202.98 :8081/T/a/api/rows/cat/ect/tickets )Bodyに適用されるPostmanの次のフィルターを使用し、rawオプションとJSON(application/json)オプションを選択します。

Filters in Postman

{
  "filter": {
    "filters": [
      {
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
      },
      {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
      },
      {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
      },
      {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
      }],
     "logic": "and"
    }
}

データが保存されるデータベースはCassandraであり、以下のリンクに従って Cassandra not equal operatorCassandra OR =演算子Cassandra演算子間の順序 、CassandraはNOT EQUAL TO[〜#〜]または[〜#〜][〜#〜] between [〜#〜]演算子。したがって、[〜#〜] and [〜#〜を除いて、これらの演算子でURLをフィルタリングする方法はありません。 ]

Second、次のコードを使用して、要求ライブラリに単純なフィルターを適用しています。

import requests
payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=payload)

しかし、私が持っているのは、一時的な劣化ではないチケットだけではなく、チケットの完全なデータです。

Third、システムは実際に動作していますが、データを表示するのに2〜3分遅れています。ロジックは次のようになります:8人のユーザーがあり、ユーザーごとに一時的な低下ではないすべてのチケットを表示したい場合は、実行します

def get_json():
    if user_name == "user 001":
        with urllib.request.urlopen(
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&001",timeout=15) as url:
            complete_data = json.loads(url.read().decode())

    Elif user_name == "user 002":
        with urllib.request.urlopen(             
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&002",timeout=15) as url:
            complete_data = json.loads(url.read().decode())
    return complete_data

def get_tickets_not_temp_degradation(start_date,end_date,complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

基本的に、現在と昨年からチケットのセット全体を取得してから、Pythonを使用して完全なセットをユーザーごとにフィルタリングします。これまでのところ、このプロセスは10ユーザーのみです。 10回繰り返され、遅延が発生する理由を発見しても驚きません...

私の質問は、リクエストライブラリのこの問題をどのように修正できますか?私は次のリンクを使用しています Requests library documentation それを機能させるチュートリアルとして使用していますが、ペイロードが読み取られていないようです。

7
abautista

PostmanリクエストはJSON本文です。同じ本体をPythonで再現するだけです。 PythonコードはJSONを送信しておらず、Postmanサンプルと同じデータを送信していません。

まず、data引数を介して辞書を送信すると、その辞書はJSONではなく_application/x-www-form-urlencoded_形式にエンコードされます。次に、単一のフィルターを送信しているように見えます。

次のコードは、Postmanの投稿を正確に複製します。

_import requests

filters = {"filter": {
    "filters": [{
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
    }, {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
    }, {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
    }, {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
    }],
    "logic": "and"
}}

url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
response = requests.post(url, json=filters)
_

ここでfiltersPythonデータ構造であり、jsonキーワード引数に渡されることに注意してください。後者を使用すると、次の2つのことが行われます。

  • Pythonデータ構造をJSONにエンコードします(生のPostman本文値とまったく同じJSON値を生成します)。
  • _Content-Type_ヘッダーを_application/json_に設定します(本文のJSONを選択した後、ドロップダウンメニューでrawオプションを選択してPostman設定で行ったように)。

requestsはそれ以外の場合HTTP APIのみで、Cassandra他のどのHTTPライブラリよりも多く行うことはできません。_urllib.request.urlopen_コードはGETリクエストを送信します。そして、次のようにrequestsに簡単に変換されます:

_def get_json():
    url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
    response = requests.get(url, params={'user_name': user}, timeout=15)    
    return response.json()
_

if分岐を削除し、params引数を使用して置換しました。これは、キーと値のペアの辞書を正しくエンコードされたURLクエリに変換します(ユーザー名を_user_name_キーとして渡します)。

応答のjson()呼び出しに注意してください。これにより、サーバーから返されるJSONデータのデコードが処理されます。これにはまだ時間がかかります。ここでは、Cassandraデータをあまりフィルタリングしていません。

9
Martijn Pieters

データの代わりにjson属性を使用することをお勧めします。ダンプを処理します。

import requests

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, json=data)

更新、質問3の回答。urllibを使用している理由はありますか?このリクエストにはpythonリクエストも使用します。

import requests

def get_json():
    r = requests.get("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets”, params={"user_name": user_name.replace(" ", "&")})

    return r.json

# not sure what you’re doing here, more context/code example would help
def get_tickets_not_temp_degradation(start_date, end_date, complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

また、ユーザー名は本当にuser+001user&001またはuser 001

5
teewuane

私の経験は次のとおりです。urllibを試し、APIを処理するためにpythonで多くのことを要求しました。とても問題です。通常、GETリクエストは簡単ですが、POSTリクエストには非常に問題があります。 (ペイロードの場合のように)動作しない場合もありますが、さらに悪い場合は動作が悪くなります。最近テストに合格したこのスクリプトがありましたが、本番では一部のケースで機能しませんでした。特殊文字(ポルトガル語のãáなど)を含むリクエストが機能しないことがわかりました。 :(
ある時点で、「このブラックボックスの依存関係で地獄に行く」と言いました。実際のところ、pythonまたは他のスクリプト言語なしでAPI呼び出しを行うことができます(少なくともbashが必要です)。 UNIXユーザーは、すべてにCURLを使用できます。それは解放です!動作しない例、言語のバージョン、httpライブラリはこれ以上ありません。端末からcurlリクエストを送信し、必要なものが機能するかどうかを確認します。あなたの場合は次のようになります:

curl -H "Content-Type: application/json" -d '{"field":"T_Subcategory","operator":"neq","value":"Temporary Degradation"}' "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"

次に、GET用に次のpythonスクリプトを作成します。

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

POSTの場合:

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

data = {"my":"phyton_dictionary"}
data = json.dumps(data) #this is a json string now

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, -d, data, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

python関数でこれらの2つのプロトタイプを変換し、他の呼び出しが必要なときに「ライブラリ」を作成するのは非常に簡単です。必要なAPIを扱っている場合は、手動でURLパラメーターを作成できます。

したがって、この答えはリクエストに関する特定の問題を解決するものではありません。私はそれらの問題の多くがあり、試行錯誤のハッキングスタイルでいくつかを解決し、最終的にAPIスクリプトを構築する方法を変更し、可能な限りすべての依存関係を削除することで問題を解決したことを伝えます非常にきれいなスクリプト。ドキュメントに到達する必要のあるURLと送信する必要のあるヘッダーがドキュメントにある場合、問題は二度とありません。

それが役に立てば幸い。

0
Alex

私は、次のようにリクエストライブラリを使用できると思います:

import requests
import json

payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=json.dumps(payload))
0
juanblo

ユーザーをURLで送信し、ポストで使用しますが、エンドポイントの実装方法によって異なります。以下のコードを試すことができます:

import requests
from json import dumps

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, data=dumps(data))
0
anuj249