Zgłaszanie żądania do RESTful API przy użyciu Pythona

221

Mam interfejs API RESTful, który ujawniłem za pomocą implementacji Elasticsearch w instancji EC2 w celu zindeksowania korpusu treści. Mogę wysłać zapytanie do wyszukiwania, uruchamiając z mojego terminala (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": {}
}'

Jak zamienić powyższe w żądanie API za pomocą python/requestslub python/urllib2(nie jestem pewien, który wybrać - korzystałem z urllib2, ale słyszę, że żądania są lepsze ...)? Czy przekazuję jako nagłówek czy w inny sposób?

użytkownik7289
źródło

Odpowiedzi:

340

Za pomocą wniosków :

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)

W zależności od rodzaju reakcji Twoich zwrotów API, będzie to prawdopodobnie chcesz spojrzeć na response.textlub response.json()(ewentualnie skontrolować response.status_codepierwszy). Zobacz tutaj dokumenty szybkiego startu , szczególnie w tej sekcji .

andersschuller
źródło
3
myślę, że powinno to być: response = requests.post (url, data = data)
CK.Nguyen
8
„requests.get” nie przyjmuje parametru „data”. Może przyjmować opcjonalny parametr „params”, który zwykle jest ciągiem zapytania zawierającego dykt. Jeśli ładunek jest niezbędny do pobrania danych (taki jak przykład zamieszczony w pytaniu), należy użyć „requests.post”. Dodatkowo użycie biblioteki „json” ułatwia parsowanie odpowiedzi json.
HVS
4
@ParveenShukhala „Żądania oficjalnie obsługują Python 2.6–2.7 i 3.3–3.5 i działają świetnie na PyPy”. - pypi.python.org/pypi/requests
danio
2
Ponieważ wysyłasz JSON, możesz użyć parametru json zamiast danych takich jak: response = requests.post (url, json = data)
Mark Chorley
101

Korzystanie z żądań i json sprawia, że ​​jest to proste.

  1. Zadzwoń do API
  2. Zakładając, że API zwraca JSON, parsuj obiekt JSON w dict Pythona za pomocą json.loadsfunkcji
  3. Pętlę przez dykta, aby uzyskać informacje.

Moduł żądań zapewnia przydatną funkcję zapętlania sukcesu i niepowodzenia.

if(Response.ok): pomoże ustalić, czy połączenie API zakończyło się powodzeniem (kod odpowiedzi - 200)

Response.raise_for_status() pomoże ci pobrać kod http, który jest zwracany z API.

Poniżej znajduje się przykładowy kod do wykonywania takich wywołań API. Można również znaleźć w github . Kod zakłada, że ​​interfejs API korzysta z uwierzytelniania skrótu. Możesz to pominąć lub użyć innych odpowiednich modułów uwierzytelniania, aby uwierzytelnić klienta wywołującego interfejs 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()
HVS
źródło
2
Ostatnia część z iteracją po kluczach nie zawsze będzie działać, ponieważ dokument JSON może mieć tablicę jako element najwyższego poziomu. Błędem byłoby więc spróbowaćjData[key]
Denis The Menace
@DenisTheMenace, jeśli jest to tablica, jak miałbym ją zapętlić?
qasimalbaqali
@qasimalbaqali w ten sam sposób, w jaki przeglądasz słownik. Ale elementy tablicy będą po prostu jData, a niejData[key]
Denis The Menace
Sidenote: Jeśli Twój interfejs API zwraca dużą odpowiedź JSON, możesz wydrukować go w następujący sposób: print(json.dumps(jData, indent=4, sort_keys=True))
Marco
2
W Pythonie 3 wyrzucono: „JSON musi być str nie bajtami”. Zostało to naprawione przez dekodowanie wyjścia, tj. Json.loads (myResponse.content.decode ('utf-8')). Powinieneś także owinąć klucz i klucz jData za pomocą str (), więc gdy RESTful API zwraca liczby całkowite, nie narzeka.
Mirkules,
11

Więc chcesz przekazać dane w treści żądania GET, lepiej byłoby zrobić to w wywołaniu POST. Możesz to osiągnąć, korzystając z obu żądań.

Raw Raw

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

Przykładowe połączenie z żądaniami

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()
gvir
źródło
dostał martwy link
użytkownik3157940
4
należy użyć zmiennej nagłówki: requests.get (... nagłówki = nagłówki, ....)
Markus Meyer
9

Poniżej znajduje się program do wykonania reszty interfejsu API w 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)
Shashank G.
źródło