การร้องขอไปยัง RESTful API โดยใช้ python


221

ฉันมี 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 แต่ได้ยินว่าคำขอนั้นดีกว่า ... ) ฉันจะผ่านเป็นส่วนหัวหรืออย่างอื่นได้หรือไม่

คำตอบ:


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 = requests.post (url, data = data)
CK.Nguyen

8
"requests.get" ไม่ได้ใช้พารามิเตอร์ "data" อาจใช้พารามิเตอร์ "params" ซึ่งเป็นตัวเลือกซึ่งโดยปกติจะเป็นสตริงที่มีสตริงข้อความค้นหา หากจำเป็นต้องมี payload เพื่อดึงข้อมูล (เช่นตัวอย่างที่โพสต์ในคำถาม) ดังนั้นจำเป็นต้องใช้ "requests.post" นอกจากนี้การใช้ไลบรารี "json" ทำให้การแยกคำตอบ json ง่ายขึ้น
HVS

4
@ParveenShukhala "คำขออย่างเป็นทางการรองรับ Python 2.6–2.7 & 3.3–3.5 และทำงานได้ดีบน PyPy" - pypi.python.org/pypi/requests
danio

2
เนื่องจากเป็น JSON ที่คุณกำลังส่งคุณสามารถใช้พารามิเตอร์ json แทนข้อมูลดังนี้: response = requests.post (url, json = data)
Mark Chorley

101

การใช้คำร้องขอและjsonทำให้มันง่าย

  1. โทรหา API
  2. สมมติว่า API คืนค่า JSON ให้แยกอ็อบเจ็กต์ JSON ลงใน Pict dython โดยใช้json.loadsฟังก์ชัน
  3. วนรอบ dict เพื่อดึงข้อมูล

โมดูลคำขอให้ฟังก์ชันที่มีประโยชน์แก่คุณในการวนลูปเพื่อความสำเร็จและความล้มเหลว

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]
Denis The Menace

@ DenisTheMenace ถ้ามันเป็นอาร์เรย์ฉันจะวนรอบมันได้อย่างไร?
qasimalbaqali

@qasimalbaqali เช่นเดียวกับที่คุณวนรอบพจนานุกรม แต่องค์ประกอบอาเรย์จะเป็นแบบง่ายๆjDataไม่ใช่jData[key]
Denis The Menace

Sidenote: หาก API ของคุณส่งคืนการตอบสนอง JSON ขนาดใหญ่คุณสามารถพิมพ์ได้เช่นนี้: print(json.dumps(jData, indent=4, sort_keys=True))
Marco

2
ภายใต้ python3 ข้อมูลต่อไปนี้ถูกคายออกมา 'JSON ต้องเป็น str ไม่ใช่ไบต์' สิ่งนี้ได้รับการแก้ไขโดยการถอดรหัสเอาต์พุตเช่น json.loads (myResponse.content.decode ('utf-8')) นอกจากนี้คุณควรตัดคีย์และคีย์ jData ด้วย str () ดังนั้นเมื่อ RESTful API ส่งคืนเลขจำนวนเต็มมันจะไม่บ่น
Mirkules

11

ดังนั้นคุณต้องการส่งผ่านข้อมูลในเนื้อความของคำขอ GET ดีกว่าที่จะทำใน POST call คุณสามารถทำได้โดยใช้คำขอทั้งสอง

คำขอดิบ

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

มีลิงค์ตาย
user3157940

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.