wake-up-neo.com

Wie mache ich eine Post-Anfrage mit der Python-Request-Bibliothek?

Ich verwende die folgenden Filter in Postman, um eine POST - Anforderung in einer Web-API auszuführen, aber ich kann keine einfache POST -Anforderung in Python mit der Anforderungsbibliothek erstellen. 

Zuerst, ich sende eine POST - Anfrage an diese URL ( http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets ) mit der Die folgenden Filter in Postman wurden auf den Body angewendet, wobei die Optionen raw und JSON (application/json) ausgewählt wurden. 

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"
    }
}

Die Datenbank, in der die Daten gespeichert werden, ist Cassandra und entsprechend den folgenden Links Cassandra nicht gleich Operator , Cassandra OR Operator , Cassandra Zwischen der Reihenfolge der Operatoren , unterstützt Cassandra die NOT EQUAL TO, ODER, ZWISCHEN - Operatoren nicht. Daher kann ich die URL nicht filtern mit diesen Operatoren außer mit UND

Second, ich verwende den folgenden Code, um einen einfachen Filter mit der Anforderungsbibliothek anzuwenden. 

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)

Aber ich habe die vollständigen Daten von Tickets und nicht nur solche, die keine vorübergehende Verschlechterung darstellen. 

Drittens, das System funktioniert tatsächlich, aber wir haben eine Verzögerung von 2-3 Minuten, um die Daten zu sehen. Die Logik lautet wie folgt: Wir haben 8 Benutzer und wir möchten alle Tickets pro Benutzer anzeigen, die keine vorübergehende Verschlechterung darstellen, dann tun wir dies.:

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'])

Grundsätzlich erhalten wir alle Tickets aus dem aktuellen und letzten Jahr, dann lassen wir Python das gesamte Ticket nach Benutzer filtern. Bisher gibt es nur 10 Benutzer, was bedeutet, dass sich dieser Vorgang zehnmal wiederholt, was mich nicht überrascht Finde heraus, warum wir die Verzögerung bekommen ... 

Meine Fragen sind, wie kann ich dieses Problem der Anforderungsbibliothek beheben? Ich verwende den folgenden Link Requests-Bibliotheksdokumentation als Tutorial, damit es funktioniert, aber es scheint nur so, als würde meine Nutzlast nicht gelesen.

6
Alejandro BR

Ihre Postman-Anfrage ist ein JSON-Body. Reproduzieren Sie einfach denselben Körper in Python. Ihr Python-Code sendet weder JSON noch sendet er dieselben Daten wie Ihr Postman-Beispiel.

Wenn Sie zunächst ein Wörterbuch über die Argumente data senden, wird dieses Wörterbuch in das Formular application/x-www-form-urlencoded und nicht in JSON codiert. Zweitens scheinen Sie einen einzelnen Filter zu senden.

Der folgende Code repliziert Ihren Postman-Post genau:

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)

Beachten Sie, dass filters hier eine Python - Datenstruktur ist und an das Schlüsselwort json übergeben wird. Die Verwendung des letzteren bewirkt zwei Dinge:

  • Kodieren Sie die Python-Datenstruktur in JSON (wobei genau derselbe JSON-Wert wie der Rohwert Ihres Postman-Körpers erzeugt wird).
  • Setzen Sie den Content-Type-Header auf application/json (wie in Ihrer Postman-Konfiguration, indem Sie die Option JSON im Dropdown-Menü auswählen, nachdem Sie raw für den Körper ausgewählt haben).

requests ist ansonsten nur eine HTTP-API , es kann nicht dazu führen, dass Cassandra mehr tut als jede andere HTTP-Bibliothek. Der urllib.request.urlopen-Code sendet GET-Anforderungen und wird trivial in requests übersetzt mit:

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()

Ich entfernte die if-Verzweigung und ersetzte diese durch die Verwendung des params-Arguments, das ein Wörterbuch von Schlüsselwertpaaren in eine korrekt codierte URL-Abfrage übersetzt (den Benutzernamen als user_name-Schlüssel übergeben).

Beachten Sie den Aufruf von json() in der Antwort. Dies sorgt für die Dekodierung von vom Server zurückkommenden JSON-Daten. Dies dauert immer noch sehr lange, Sie filtern die Cassandra-Daten hier nicht sehr.

9
Martijn Pieters

Ich würde empfehlen, das Attribut json anstelle von Daten zu verwenden. Es erledigt das Dumping für Sie.

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)

Update, Antwort auf Frage 3. Gibt es einen Grund, warum Sie urllib verwenden? Ich benutze auch Python-Anfragen für diese Anfrage.

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'])

Soll der Benutzername wirklich user+001 sein und nicht user&001 oder user 001?

4
teewuane

Meine Erfahrung ist die folgende: Ich habe urllib ausprobiert und fragt viel in Python nach APIs. Es ist nur sehr problematisch. Normalerweise sind GET-Anforderungen direkt, aber POST -Anfragen sind sehr problematisch. Funktioniert manchmal nicht (wie bei Ihrer Nutzlast) oder, schlimmer noch, es funktioniert schlecht. Ich hatte dieses Skript kürzlich, das meine Tests bestanden hat, aber es funktionierte in einigen Fällen in der Produktion nicht, bis ich herausfand, dass Anforderungen mit Sonderzeichen (wie ã á in Portugiesisch) nicht funktionierten. :(
Irgendwann sagte ich: "Zur Hölle mit diesen Blackbox-Abhängigkeiten". Tatsächlich kann jeder API-Aufruf ohne Python oder eine andere Skriptsprache ausgeführt werden (zumindest benötigen Sie bash). Als UNIX-Benutzer kann CURL für ALLES verwendet werden. Es ist befreiend! Keine Beispiele mehr, die nicht funktionieren, keine weiteren Versionen von Sprachen, keine http-Bibliotheken mehr. Ich schicke einfach eine Curl-Anfrage vom Terminal und schaue, ob das, was ich möchte, funktioniert. Ihr Fall wäre:

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"

Als Nächstes baue ich das folgende Python-Skript für GET:

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)

Für 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)

Es ist sehr einfach, diese beiden Prototypen in Python-Funktionen umzuwandeln und eine "Bibliothek" zu erstellen, wenn Sie andere Aufrufe benötigen. Sie können die URL-Parameter von Hand erstellen, wenn Sie mit einer API arbeiten, die dies benötigt.

Diese Antwort löst also nicht Ihr spezifisches Problem mit Anfragen. Es sagt Ihnen nur, dass ich viele dieser Probleme hatte, einige durch Versuchs- und Fehlerhacking-Stil gelöst und schließlich das Problem gelöst habe, indem ich die Art, wie ich das API-Skript baue, änderte, indem ich alle möglichen Abhängigkeiten entfernte, bis ich eine sehr sauberes Skript. Ich hatte nie wieder Probleme, wenn die Dokumente die URL haben, die ich erreichen muss, und die Header, die ich senden muss. 

Ich hoffe es hilft.

0
Alex

Ich denke, Sie können die Anforderungsbibliothek wie folgt verwenden:

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

Sie senden einen Benutzer in der URL, verwenden ihn per Post, aber er hängt davon ab, wie Endpunkte implementiert werden. Sie können den folgenden Code ausprobieren:

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