Yêu cầu API RESTful bằng python


221

Tôi có API RESTful mà tôi đã tiếp xúc bằng cách sử dụng triển khai Elaticsearch trên phiên bản EC2 để lập chỉ mục nội dung. Tôi có thể truy vấn tìm kiếm bằng cách chạy các mục sau từ thiết bị đầu cuối của mình (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": {}
}'

Làm cách nào để tôi chuyển ở trên thành yêu cầu API bằng cách sử dụng python/requestshoặc python/urllib2(không chắc chắn nên thực hiện yêu cầu nào - đã sử dụng urllib2, nhưng nghe rằng yêu cầu đó tốt hơn ...)? Tôi có vượt qua như một tiêu đề hay không?

Câu trả lời:


340

Sử dụng yêu cầu :

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)

Tùy thuộc vào loại phản hồi mà API của bạn trả về, sau đó bạn có thể sẽ muốn xem xét response.texthoặc response.json()(hoặc có thể kiểm tra response.status_codetrước). Xem các tài liệu khởi động nhanh ở đây , đặc biệt là phần này .


3
tôi nghĩ, nó phải là:
answer = request.post

8
"request.get" không lấy tham số "dữ liệu". Nó có thể lấy tham số "params" tùy chọn, thường là một chuỗi truy vấn mang chính tả. Nếu một tải trọng là cần thiết để tìm nạp dữ liệu (chẳng hạn như ví dụ được đăng trong câu hỏi), thì "request.post" cần được sử dụng. Ngoài ra, sử dụng thư viện "json" giúp phân tích phản hồi json dễ dàng hơn.
HVS

4
@ParveenShukhala "Yêu cầu chính thức hỗ trợ Python 2.6 .22.7 & 3.3, 3.5 và chạy rất tốt trên PyPy." - pypi.python.org/pypi/requests
danio

2
Vì đây là JSON mà bạn đang gửi, bạn có thể sử dụng tham số json thay vì dữ liệu như vậy: answer = request.post (url, json = data)
Mark Chorley

101

Sử dụng các yêu cầujson làm cho nó đơn giản.

  1. Gọi API
  2. Giả sử API trả về JSON, phân tích đối tượng JSON thành một lệnh Python bằng json.loadshàm
  3. Lặp lại thông qua dict để trích xuất thông tin.

Mô-đun yêu cầu cung cấp cho bạn chức năng hữu ích để lặp lại thành công và thất bại.

if(Response.ok): sẽ giúp bạn xác định xem cuộc gọi API của bạn có thành công hay không (Mã phản hồi - 200)

Response.raise_for_status() sẽ giúp bạn tìm nạp mã http được trả về từ API.

Dưới đây là một mã mẫu để thực hiện các cuộc gọi API như vậy. Cũng có thể được tìm thấy trong github . Mã này giả định rằng API sử dụng xác thực digest. Bạn có thể bỏ qua điều này hoặc sử dụng các mô-đun xác thực phù hợp khác để xác thực ứng dụng khách gọi 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
Phần cuối cùng với các lần lặp trên các khóa sẽ không luôn hoạt động vì tài liệu JSON có thể có mảng là một phần tử mức cao nhất. Vì vậy, sẽ là một lỗi khi cố gắng để có đượcjData[key]
Denis The Menace

@DenisTheMenace nếu nó là một mảng, tôi sẽ lặp xung quanh nó như thế nào?
qasimalbaqali

@qasimalbaqali giống như cách bạn lặp qua từ điển. Nhưng các yếu tố mảng sẽ chỉ đơn giản jData, không phảijData[key]
Denis The Menace

Sidenote: Nếu API của bạn trả về một phản hồi JSON lớn, bạn có thể in nó như thế này: print(json.dumps(jData, indent=4, sort_keys=True))
Marco

2
Trong python3, phần sau đây đã được đưa ra 'JSON phải là str chứ không phải byte'. Điều này được khắc phục bằng cách giải mã đầu ra, tức là json.loads (myResponse.content.decode ('utf-8')). Ngoài ra, bạn nên bọc khóa và khóa jData bằng str () để khi API RESTful trả về số nguyên, nó không phàn nàn.
Mirkules

11

Vì vậy, bạn muốn truyền dữ liệu trong phần thân của một yêu cầu GET, tốt hơn là thực hiện nó trong cuộc gọi POST. Bạn có thể đạt được điều này bằng cách sử dụng cả hai Yêu cầu.

Yêu cầu thô

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

Cuộc gọi mẫu với Yêu cầu

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

có một liên kết chết ở đó
user3157940

4
biến tiêu đề nên được sử dụng: request.get (... headers = headers, ....)
Markus Meyer

9

Dưới đây là chương trình thực thi api còn lại trong 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.