Здійснення запиту до API RESTful за допомогою python


221

У мене є API RESTful, який я викрив, використовуючи реалізацію Elasticsearch на екземплярі EC2, щоб індексувати корпус вмісту. Я можу запитати пошук, запустивши в своєму терміналі (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": {}
}'

Як я перетворять вище на запит API, використовуючи python/requestsабо python/urllib2(не впевнений, для кого потрібно звернутися - використовував urllib2, але чути, що запити краще ...)? Я пропускаю як заголовок чи іншим чином?

Відповіді:


340

Використання запитів :

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)

Залежно від того, який тип відповіді повертає ваш API, ви, ймовірно, захочете переглянути response.textабо response.json()(або, можливо, response.status_codeспочатку перевірити ). Дивіться документи швидкого запуску тут , особливо цей розділ .


3
я думаю, це повинно бути: response =
questions.post

8
"request.get" не приймає параметр "data". Він може приймати необов'язковий параметр "params", який зазвичай є dict рядком запиту. Якщо для отримання даних потрібна корисна навантаження (наприклад, розміщений у відповідному прикладі), тоді потрібно використовувати "questions.post". Крім того, використання бібліотеки "json" полегшує розбір відповіді json.
HVS

4
@ParveenShukhala "Запити офіційно підтримують Python 2.6-2.7 та 3.3-33.5, і чудово працює на PyPy." - pypi.python.org/pypi/requests
danio

2
Оскільки це JSON, який ви надсилаєте, ви можете використовувати параметр json, а не такі дані як: response = questions.post (url, json = data)
Марк Чорлі

101

Використання запитів і json робить його простим.

  1. Викличте API
  2. Якщо припустимо, що API повертає JSON, проаналізуйте об'єкт JSON в диктові Python, використовуючи json.loads функції
  3. Проведіть цикл через дік для отримання інформації.

Модуль запитів надає корисну функцію для циклу успіху та невдачі.

if(Response.ok): допоможе визначити, чи вдалий ваш виклик API (код відповіді - 200)

Response.raise_for_status() допоможе вам отримати http-код, який повертається з API.

Нижче наведено зразок коду для здійснення таких дзвінків API. Також можна знайти в github . Код передбачає, що API використовує дайджест аутентифікації. Можна або пропустити це, або використовувати інші відповідні модулі аутентифікації для автентифікації клієнта, що викликає 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
Остання частина з ітерацією клавіш не завжди працюватиме, оскільки документ JSON може мати масив як елемент верхнього рівня. Отже, спробувати дістатисьjData[key]
Дениса Мена

@DenisTheMenace, якщо це масив, як би я обертався навколо нього?
qasimalbaqali

@qasimalbaqali так само, як ви перебираєте словник. Але елементів масиву буде просто jData, а неjData[key]
Денис Грозний

Sidenote: Якщо ваш API поверне велику відповідь JSON, ви можете досить роздрукувати його так: print(json.dumps(jData, indent=4, sort_keys=True))
Marco

2
Під python3 було виписано наступне: "JSON must be str not bytes". Це фіксується за допомогою декодування виводу, тобто json.loads (myResponse.content.decode ('utf-8')). Також слід обернути ключ та ключ jData з str (), тому коли API RESTful повертає цілі числа, він не скаржиться.
Міркулес

11

Отже, ви хочете передати дані в тіло GET-запиту, краще було б зробити це у виклику POST. Ви можете досягти цього, використовуючи обидва Запити.

Сирий запит

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

Зразок дзвінка із запитами

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

потрапив до мертвого посилання
користувач3157940

4
слід використовувати змінну заголовків:
Markus Meyer

9

Нижче представлена ​​програма для виконання решти api в 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.