Python kullanarak RESTful API'ye istekte bulunma


221

Ben bir içerik topluluğunu endekslemek için bir EC2 örneği üzerinde Elasticsearch bir uygulama kullanarak maruz RESTful API var. Terminalimden (MacOSX) aşağıdakileri çalıştırarak aramayı sorgulayabilirim:

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

Yukarıda python/requestsveya kullanarak bir API isteğine nasıl dönüştürebilirim python/urllib2(hangisini kullanacağınızdan emin değilim - urllib2 kullanıyor ancak isteklerin daha iyi olduğunu duyuyorum ...)? Üstbilgi olarak mı yoksa başka türlü mi?

Yanıtlar:


340

İstekleri kullanma :

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'nizin ne tür bir yanıt döndürdüğüne bağlı olarak, muhtemelen daha sonra bakmak response.textveya response.json()(veya response.status_codeönce incelemek ) isteyeceksiniz . Hızlı başlangıç dokümanlar bakın burada , özellikle bu bölümü .


3
bence, olmalı: response = requests.post (url, veri = veri)
CK.Nguyen

8
"requests.get", "data" parametresini almaz. Genellikle sorgu dizesi taşıyan bir dikte olan isteğe bağlı "params" parametresini alabilir. Verileri almak için bir yük gerekiyorsa (söz konusu yayınlanan örnek gibi), "requests.post" kullanılmalıdır. Ayrıca "json" kitaplığı kullanmak json yanıtını ayrıştırmayı kolaylaştırır.
HVS

4
@ParveenShukhala "İstekler resmi olarak Python 2.6-2.7 ve 3.3-3.5'i destekliyor ve PyPy'de harika çalışıyor." - pypi.python.org/pypi/requests
danio

2
Göndermekte olduğunuz JSON olduğundan, json parametresini aşağıdaki gibi veriler yerine kullanabilirsiniz: response = requests.post (url, json = veri)
Mark Chorley

101

İstekleri ve json kullanmak bunu kolaylaştırır.

  1. API'yı arayın
  2. API'nin bir JSON döndürdüğü varsayılarak, JSON nesnesini json.loadsişlevi kullanarak bir Python dict içine ayrıştırın
  3. Bilgi almak için dikte boyunca döngü yapın.

İstekler modülü, başarı ve başarısızlık için döngü için kullanışlı bir işlev sağlar.

if(Response.ok): API çağrınızın başarılı olup olmadığını belirlemenize yardımcı olur (Yanıt kodu - 200)

Response.raise_for_status() API'dan döndürülen http kodunu getirmenize yardımcı olur.

Aşağıda bu tür API çağrıları yapmak için örnek bir kod verilmiştir. Ayrıca github'da bulunabilir . Kod, API'nin özet kimlik doğrulamasını kullandığını varsayar. API'yı çağıran istemcinin kimliğini doğrulamak için bunu atlayabilir veya diğer uygun kimlik doğrulama modüllerini kullanabilirsiniz.

#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 belgesi üst düzey öğe olarak dizi içerebileceğinden, anahtarlar üzerinden yineleme içeren son bölüm her zaman çalışmaz. Yani, denemek için bir hata olurdujData[key]
Denis The Menace

@DenisTheMenace bir dizi ise, nasıl döngü olur?
qasimalbaqali

@ qasimalbaqali sözlük üzerinde döngü gibi. Ancak dizi öğeleri basit olacak jData, değiljData[key]
Denis The Menace

Sidenote: API'nız büyük bir JSON yanıtı döndürürse, bunu şu şekilde yazdırabilirsiniz: print(json.dumps(jData, indent=4, sort_keys=True))
Marco

2
Python3 altında, aşağıdaki 'JSON str değil bayt olmalıdır' tükürdü. Bu, çıktı kodu çözülerek giderilir, yani json.loads (myResponse.content.decode ('utf-8')). Ayrıca RESTful API tamsayılar döndürdüğünde şikayet etmeyecek şekilde str ve jData tuşlarını str () ile sarmalısınız.
Mirkules

11

Yani bir GET isteğinin gövdesine veri iletmek istiyorsanız, POST çağrısında yapmak daha iyi olur. Bunu her iki İsteği kullanarak da gerçekleştirebilirsiniz.

Ham İstek

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

Taleplerle örnek çağrı

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

orada ölü bir bağlantı var
user3157940 27:18

4
üstbilgiler değişkeni kullanılmalıdır: requests.get (... üstbilgiler = üstbilgiler, ....)
Markus Meyer

9

Aşağıda python'da kalan api'yi yürütmek için program

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.