Effettuare una richiesta a un'API RESTful utilizzando Python


221

Ho un'API RESTful che ho esposto usando un'implementazione di Elasticsearch su un'istanza EC2 per indicizzare un corpus di contenuti. Posso interrogare la ricerca eseguendo quanto segue dal mio terminale (MacOSX):

curl -XGET 'http://ES_search_demo.com/document/record/_search?pretty=true' -d '{
  "query": {
    "bool": {
      "must": [
        {
          "text": {
            "record.document": "SOME_JOURNAL"
          }
        },
        {
          "text": {
            "record.articleTitle": "farmers"
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  },
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": {}
}'

Come posso trasformarmi in una richiesta API usando python/requestso python/urllib2(non sono sicuro di quale scegliere - ho usato urllib2, ma sento che le richieste sono migliori ...)? Passo come intestazione o altro?

Risposte:


340

Utilizzando le richieste :

import requests
url = 'http://ES_search_demo.com/document/record/_search?pretty=true'
data = '''{
  "query": {
    "bool": {
      "must": [
        {
          "text": {
            "record.document": "SOME_JOURNAL"
          }
        },
        {
          "text": {
            "record.articleTitle": "farmers"
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  },
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": {}
}'''
response = requests.post(url, data=data)

A seconda del tipo di risposta che restituisce la tua API, probabilmente vorrai guardare response.texto response.json()(o possibilmente ispezionare response.status_codeprima). Consulta i documenti di avvio rapido qui , in particolare questa sezione .


3
penso che dovrebbe essere: response =
request.post

8
"request.get" non accetta il parametro "data". Potrebbe richiedere il parametro "params" facoltativo che di solito è un dict che trasporta una stringa di query. Se è necessario un payload per recuperare i dati (come l'esempio pubblicato in questione), è necessario utilizzare "request.post". Inoltre, l'utilizzo della libreria "json" semplifica l'analisi della risposta json.
HVS,

4
@ParveenShukhala "Le richieste supportano ufficialmente Python 2.6–2.7 e 3.3–3.5 e funzionano alla grande su PyPy." - pypi.python.org/pypi/requests
danio

2
Poiché è JSON che stai inviando, puoi utilizzare il parametro json anziché i dati in questo modo: response = request.post (url, json = data)
Mark Chorley,

101

utilizzando request e json lo rende semplice.

  1. Chiama l'API
  2. Supponendo che l'API restituisca un JSON, analizza l'oggetto JSON in un dict Python utilizzando json.loads funzione
  3. Passa attraverso il dict per estrarre informazioni.

richieste modulo fornisce una funzione utile per eseguire il ciclo in caso di esito positivo o negativo.

if(Response.ok): ti aiuterà a determinare se la tua chiamata API ha esito positivo (codice di risposta - 200)

Response.raise_for_status() ti aiuterà a recuperare il codice http restituito dall'API.

Di seguito è riportato un codice di esempio per effettuare tali chiamate API. Inoltre può essere trovato in github . Il codice presuppone che l'API utilizzi l'autenticazione digest. È possibile saltare questo o utilizzare altri moduli di autenticazione appropriati per autenticare il client che richiama l'API.

#Python 2.7.6
#RestfulClient.py

import requests
from requests.auth import HTTPDigestAuth
import json

# Replace with the correct URL
url = "http://api_url"

# It is a good practice not to hardcode the credentials. So ask the user to enter credentials at runtime
myResponse = requests.get(url,auth=HTTPDigestAuth(raw_input("username: "), raw_input("Password: ")), verify=True)
#print (myResponse.status_code)

# For successful API call, response code will be 200 (OK)
if(myResponse.ok):

    # Loading the response data into a dict variable
    # json.loads takes in only binary or string variables so using content to fetch binary content
    # Loads (Load String) takes a Json file and converts into python data structure (dict or list, depending on JSON)
    jData = json.loads(myResponse.content)

    print("The response contains {0} properties".format(len(jData)))
    print("\n")
    for key in jData:
        print key + " : " + jData[key]
else:
  # If response code is not ok (200), print the resulting http error code with description
    myResponse.raise_for_status()

2
L'ultima porzione con iterazione su chiavi non funzionerà sempre perché il documento JSON potrebbe avere un array come elemento di livello superiore. Quindi, sarebbe un errore cercare di ottenerejData[key]
Denis The Menace,

@DenisTheMenace se si tratta di un array, come potrei girarci attorno?
qasimalbaqali,

@qasimalbaqali nello stesso modo in cui esegui il ciclo sul dizionario. Ma gli elementi dell'array saranno semplicemente jDatanojData[key]
Denis The Menace,

Sidenote: se l'API restituisce una risposta JSON di grandi dimensioni, puoi stamparla in questo modo: print(json.dumps(jData, indent=4, sort_keys=True))
Marco

2
Sotto python3, è stato espulso 'JSON deve essere str non byte'. Questo problema viene risolto decodificando l'output, ovvero json.loads (myResponse.content.decode ('utf-8')). Inoltre dovresti avvolgere key e jData key con str (), quindi quando l'API RESTful restituisce numeri interi, non si lamenta.
Mirkules,

11

Quindi vuoi passare i dati nel corpo di una richiesta GET, meglio sarebbe farlo nella chiamata POST. È possibile ottenere ciò utilizzando entrambe le richieste.

Richiesta non elaborata

GET http://ES_search_demo.com/document/record/_search?pretty=true HTTP/1.1
Host: ES_search_demo.com
Content-Length: 183
User-Agent: python-requests/2.9.0
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate

{
  "query": {
    "bool": {
      "must": [
        {
          "text": {
            "record.document": "SOME_JOURNAL"
          }
        },
        {
          "text": {
            "record.articleTitle": "farmers"
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  },
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": {}
}

Chiamata di esempio con richieste

import requests

def consumeGETRequestSync():
data = '{
  "query": {
    "bool": {
      "must": [
        {
          "text": {
            "record.document": "SOME_JOURNAL"
          }
        },
        {
          "text": {
            "record.articleTitle": "farmers"
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  },
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": {}
}'
url = 'http://ES_search_demo.com/document/record/_search?pretty=true'
headers = {"Accept": "application/json"}
# call get service with headers and params
response = requests.get(url,data = data)
print "code:"+ str(response.status_code)
print "******************"
print "headers:"+ str(response.headers)
print "******************"
print "content:"+ str(response.text)

consumeGETRequestSync()

ottenuto un link morto lì
user3157940

4
va usata la variabile headers: request.get (... headers = headers, ....)
Markus Meyer

9

Di seguito è riportato il programma per eseguire il resto API in Python-

import requests
url = 'https://url'
data = '{  "platform": {    "login": {      "userName": "name",      "password": "pwd"    }  } }'
response = requests.post(url, data=data,headers={"Content-Type": "application/json"})
print(response)
sid=response.json()['platform']['login']['sessionId']   //to extract the detail from response
print(response.text)
print(sid)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.