J'utilise les filtres suivants dans Postman pour effectuer une demande POST dans une API Web, mais je ne parviens pas à effectuer une simple POST demande en Python avec la bibliothèque de demandes.
First, j'envoie une POST demande à cette URL ( http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets ) avec les filtres suivants dans Postman appliqués au Body, avec les options raw et JSON (application/json) sélectionnées.
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"
}
}
La base de données où sont stockées les données est Cassandra et, selon les liens suivants Cassandra n’est pas l’opérateur égal , Cassandra OR l’opérateur , Cassandra Entre ordre des opérateurs , Cassandra ne prend pas en charge les opérateurs NOT EGAL TO, OU, ENTRE, il est donc impossible de filtrer l'URL. avec ces opérateurs sauf avec ET.
Second, j'utilise le code suivant pour appliquer un filtre simple à la bibliothèque de requêtes.
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)
Mais ce que j’ai, c’est les données complètes des tickets au lieu de ceux qui ne sont pas des dégradations temporaires.
Troisième, le système fonctionne réellement mais nous attendons un délai de 2-3 minutes pour voir les données. La logique est la suivante: Nous avons 8 utilisateurs et nous voulons voir tous les tickets par utilisateur qui ne constituent pas une dégradation temporaire.:
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'])
En gros, nous obtenons l’ensemble complet des tickets de l’année en cours et de l’année dernière, puis nous laissons Python filtrer l’ensemble complet par utilisateur; jusqu’à présent, il n’ya que 10 utilisateurs, ce qui signifie que ce processus est répété 10 fois et ne me surprend Découvrez pourquoi nous avons le retard ...
Ma question est comment puis-je résoudre ce problème de la bibliothèque de demandes? J'utilise le lien suivant Demande la documentation de la bibliothèque comme didacticiel pour le faire fonctionner, mais il semble simplement que ma charge utile ne soit pas en cours de lecture.
Votre requête Postman est un corps JSON. Il suffit de reproduire ce même corps en Python. Votre code Python n'envoie pas de JSON, ni les mêmes données que votre exemple Postman.
Pour commencer, l'envoi d'un dictionnaire via les arguments data
permet de coder ce dictionnaire au format application/x-www-form-urlencoded
et non au format JSON. Deuxièmement, vous semblez envoyer un seul filtre.
Le code suivant reproduit exactement votre message 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)
Notez que filters
est une structure Python data ici, et qu’elle est transmise à l’argument json
. Utiliser ce dernier fait deux choses:
Content-Type
sur application/json
(comme vous l'avez fait dans votre configuration Postman en sélectionnant l'option JSON
dans le menu déroulant après avoir sélectionné raw
pour le corps).requests
est sinon juste une API HTTP , cela ne peut pas faire que Cassandra fasse plus que toute autre bibliothèque HTTP. Le code urllib.request.urlopen
envoie des demandes GET
et est traduit trivialement en requests
avec:
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()
J'ai supprimé la branche if
et l'ai remplacée par l'argument params
, qui traduit un dictionnaire de paires clé-valeur en une requête URL correctement codée (en passant le nom d'utilisateur sous la forme de la clé user_name
).
Notez l'appel json()
sur la réponse; cela prend en charge le décodage des données JSON provenant du serveur. Cela prend encore longtemps, vous ne filtrez pas beaucoup les données Cassandra ici.
Je recommanderais d'utiliser l'attribut json
au lieu de data. Il gère le dumping pour vous.
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)
Mise à jour, réponse à la question 3. Y a-t-il une raison pour laquelle vous utilisez urllib? J’utiliserais également des requêtes Python pour cette requête.
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'])
De plus, le nom d'utilisateur est-il vraiment censé être user+001
et non pas user&001
ou user 001
?
Mon expérience est la suivante: J'ai essayé urllib et demande beaucoup en python pour gérer les API. C'est juste très problématique. Les requêtes GET sont généralement simples, mais les requêtes POST sont très problématiques. Parfois, cela ne fonctionne pas (comme dans le cas de votre charge utile), ou pire, cela fonctionne mal. J'ai eu ce script qui a récemment passé avec succès mes tests, mais cela n'a pas fonctionné dans certains cas en production, jusqu'à ce que je découvre que les requêtes contenant des caractères spéciaux (comme ã á en portugais) ne fonctionnaient pas. :(
À un moment donné, j'ai dit "au diable avec ces dépendances de la boîte noire". En fait, on peut faire n'importe quel appel d'API sans python ou tout autre langage de script (enfin, vous avez besoin de bash au moins). En tant qu'utilisateur UNIX, vous pouvez utiliser CURL pour TOUT. C'est libérateur! Plus d'exemples qui ne fonctionnent pas, plus de versions de langues, plus de bibliothèques http. Je viens d'envoyer une demande de curl du terminal et voir si ce que je veux fonctionne. Votre cas serait:
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"
Ensuite, je construis le script python suivant pour 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)
Pour 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)
Il est très facile de transformer ces deux prototypes en fonctions python et de créer une "bibliothèque", car vous avez besoin d'autres appels. Vous pouvez créer les paramètres d'URL manuellement si vous utilisez une API qui en a besoin.
Donc, cette réponse ne résout pas votre problème spécifique avec les demandes. Cela vous indique simplement que j'ai eu beaucoup de ces problèmes, résolu quelques-uns par style de piratage par essais et erreurs, et finalement résolu en modifiant la façon dont je construis le script API, en supprimant toutes les dépendances que je pouvais script très propre. Je n'ai plus eu de problèmes si les docs ont l'URL que je dois atteindre et les en-têtes que je dois envoyer.
J'espère que ça aide.
Je pense que vous pouvez utiliser la bibliothèque de requêtes comme suit:
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))
Vous envoyez un utilisateur en url, utilisez-le via post, mais cela dépend de la manière dont les points de terminaison sont mis en œuvre. Vous pouvez essayer le code ci-dessous:
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))