Выполнение запроса к RESTful API с использованием Python

У меня есть RESTful API, который я продемонстрировал с помощью реализации 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, но слышали, что запросы лучше ...)? Я передаю как заголовок или как-то иначе?


person user7289    schedule 25.06.2013    source источник


Ответы (4)


Используя запросы:

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). См. Документацию по быстрому запуску здесь, особенно этот раздел.

person andersschuller    schedule 25.06.2013
comment
я думаю, это должно быть: response = requests.post (url, data = data) - person CK.Nguyen; 02.07.2015
comment
request.get не принимает параметр данных. Он может принимать необязательный параметр params, который обычно представляет собой строку запроса, содержащую dict. Если для получения данных необходима полезная нагрузка (например, в примере, опубликованном в вопросе), то необходимо использовать request.post. Кроме того, использование библиотеки json упрощает анализ ответа json. - person HVS; 26.01.2016
comment
@ParveenShukhala Requests официально поддерживает Python 2.6–2.7 и 3.3–3.5 и отлично работает на PyPy. - pypi.python.org/pypi/requests - person danio; 15.12.2016
comment
Поскольку вы отправляете JSON, вы можете использовать параметр json, а не такие данные: response = requests.post (url, json = data) - person Mark Chorley; 12.01.2018

Использование запросов и json упрощает задачу.

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

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

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()
person HVS    schedule 22.09.2015
comment
Последняя часть с итерацией по ключам не всегда будет работать, потому что документ JSON может иметь массив в качестве элемента верхнего уровня. Таким образом, было бы ошибкой пытаться получить jData[key] - person Denis The Menace; 28.06.2016
comment
@DenisTheMenace, если это массив, как мне его обойти? - person qasimalbaqali; 12.03.2017
comment
@qasimalbaqali так же, как вы перебираете словарь. Но элементы массива будут просто jData, а не jData[key]. - person Denis The Menace; 13.03.2017
comment
Примечание: если ваш API возвращает большой ответ JSON, вы можете распечатать его следующим образом: print(json.dumps(jData, indent=4, sort_keys=True)) - person Marco; 01.11.2017
comment
В python3 было выдано следующее: «JSON должен быть str, а не байтами». Это исправляется декодированием вывода, то есть json.loads (myResponse.content.decode ('utf-8')). Также вы должны заключить ключ и ключ jData в str (), чтобы, когда RESTful API возвращал целые числа, он не жаловался. - person Mirkules; 08.06.2018

Итак, вы хотите передать данные в теле запроса 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()
person gvir    schedule 19.01.2016
comment
там мертвая ссылка - person Nick; 27.01.2018
comment
Следует использовать переменную заголовков: requests.get (... headers = headers, ....) - person Markus Meyer; 15.03.2019

Ниже приведена программа для выполнения остальных 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)
person Shashank G    schedule 18.05.2017