จะส่งคำขอ POST ได้อย่างไร


260

ฉันพบสคริปต์นี้ออนไลน์:

import httplib, urllib
params = urllib.urlencode({'number': 12524, 'type': 'issue', 'action': 'show'})
headers = {"Content-type": "application/x-www-form-urlencoded",
            "Accept": "text/plain"}
conn = httplib.HTTPConnection("bugs.python.org")
conn.request("POST", "", params, headers)
response = conn.getresponse()
print response.status, response.reason
302 Found
data = response.read()
data
'Redirecting to <a href="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
conn.close()

แต่ฉันไม่เข้าใจวิธีการใช้กับ PHP หรือทุกอย่างภายในตัวแปร params คืออะไรหรือจะใช้อย่างไร ฉันขอความช่วยเหลือเล็กน้อยจากการพยายามทำให้มันใช้งานได้หรือไม่?


1
คำขอโพสต์เป็นเพียงคำขอโพสต์โดยไม่คำนึงถึงสิ่งที่อยู่ในฝั่งเซิร์ฟเวอร์
Ondra Žižka

7
สิ่งนี้จะส่งคำขอ POST จากนั้นเซิร์ฟเวอร์ตอบสนองด้วยส่วนหัว 302 (เปลี่ยนเส้นทาง) ไปยัง POST ของคุณ มีอะไรผิดปกติจริงหรือ
ddinchev

1
สคริปต์นี้ไม่ได้ดู python3.2 compat
jdi

python3 ที่เทียบเท่ากับตัวอย่างนี้อาจเป็น: pastebin.com/Rx4yfknM
jdi

1
สิ่งที่ฉันจะแนะนำคือติดตั้งlive http headeraddon ของ firefox และเปิด url ของคุณใน firefox และดูrequest/responseurl ในlive http headeraddon มากกว่าที่คุณจะเข้าใจparams and headersในโค้ดของคุณ
RanRag

คำตอบ:


388

ถ้าคุณอยากจะจับกับ HTTP ใช้งูหลามผมขอแนะนำให้จอง: HTTP สำหรับมนุษย์ POST quickstart ปรับให้เหมาะกับคำถามของคุณคือ:

>>> import requests
>>> r = requests.post("http://bugs.python.org", data={'number': 12524, 'type': 'issue', 'action': 'show'})
>>> print(r.status_code, r.reason)
200 OK
>>> print(r.text[:300] + '...')

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Issue 12524: change httplib docs POST example - Python tracker

</title>
<link rel="shortcut i...
>>> 

ฉันไม่สามารถรับผลลัพธ์เดียวกันกับที่คุณทำไว้ด้านบน ฉันเขียนหมายเลขปัญหาอื่นลงบนหน้าแล้วเรียกใช้สคริปต์ แต่ฉันไม่เห็นหมายเลขปัญหาของผลลัพธ์
Efe Büyük

2
โปรดเปลี่ยน data = {'number': 12524, เพื่ออ่าน data = {'number': '12524', ฉันจะเปลี่ยนมันเอง แต่การแก้ไขจะต้องมีมากกว่า 6 ตัวอักษร ขอบคุณ
kevthanewversi

2
วิธีรับผล json
Yohanes AI

9
หากคุณต้องการส่งวัตถุ JSON คุณควรทำ: json={'number': 12524...แทนdata=...
Seraf

3
ทำไมคำตอบว่า "ถ้าคุณต้องการจัดการกับ HTTP ด้วย Python" จริงๆ เป็นความคิดที่ดีที่จะจัดการคำขอ HTTP หรือไม่ ถ้าเป็นเช่นนั้นทำไม ใครช่วยอธิบายได้บ้าง
Jan Pisl

147

หากคุณต้องการให้สคริปต์พกพาได้และคุณไม่ต้องการการพึ่งพาจากบุคคลที่สามนี่คือวิธีที่คุณส่งคำขอ POST อย่างหมดจดใน Python 3

from urllib.parse import urlencode
from urllib.request import Request, urlopen

url = 'https://httpbin.org/post' # Set destination URL here
post_fields = {'foo': 'bar'}     # Set POST fields here

request = Request(url, urlencode(post_fields).encode())
json = urlopen(request).read().decode()
print(json)

ตัวอย่างผลลัพธ์:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "foo": "bar"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "7", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.3"
  }, 
  "json": null, 
  "origin": "127.0.0.1", 
  "url": "https://httpbin.org/post"
}

6
รหัสนี้จะใช้งานได้ใน Python 3 เท่านั้นอย่างที่ฉันพูดในคำตอบ
สไตล์

36

คุณไม่สามารถบรรลุคำขอ POST โดยใช้urllib(สำหรับ GET เท่านั้น) ลองใช้requestsโมดูลแทนเช่น:

ตัวอย่างที่ 1.0:

import requests

base_url="www.server.com"
final_url="/{0}/friendly/{1}/url".format(base_url,any_value_here)

payload = {'number': 2, 'value': 1}
response = requests.post(final_url, data=payload)

print(response.text) #TEXT/HTML
print(response.status_code, response.reason) #HTTP

ตัวอย่าง 1.2:

>>> import requests

>>> payload = {'key1': 'value1', 'key2': 'value2'}

>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print(r.text)
{
  ...
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  ...
}

ตัวอย่างที่ 1.3:

>>> import json

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

4
ขอบคุณ ข้อมูล = json.dumps (น้ำหนักบรรทุก) เป็นกุญแจสำคัญสำหรับ USECASE ของฉัน
ซีเรีย

11

ใช้requestsไลบรารี่เพื่อ GET, POST, PUT หรือ DELETE โดยกดที่จุดสิ้นสุด REST API ผ่าน URL ปลายทางที่เหลือของ api url, payload (dict) ในdataและ header / metadataheaders

import requests, json

url = "bugs.python.org"

payload = {"number": 12524, 
           "type": "issue", 
           "action": "show"}

header = {"Content-type": "application/x-www-form-urlencoded",
          "Accept": "text/plain"} 

response_decoded_json = requests.post(url, data=payload, headers=header)
response_json = response_decoded_json.json()

print response_json

2
รหัสนี้มีปัญหากับการเยื้องและชื่อพารามิเตอร์ส่วนหัว
xilopaint

2
headersพารามิเตอร์ผิดและเรายังไม่มี json ที่นี่ เราควรใช้json.dumps(pauload)
Arash Hatami

ขอบคุณ @xilopaint และ ArashHatami สำหรับข้อผิดพลาดทางไวยากรณ์ ถูกต้องแล้ว
Pranzell

3

พจนานุกรมข้อมูลของคุณมีชื่อของฟิลด์ป้อนข้อมูลในแบบฟอร์มคุณเพียงแค่ใส่ค่าของพวกเขาเพื่อค้นหาผลลัพธ์ มุมมองแบบฟอร์ม ส่วนหัวกำหนดค่าเบราว์เซอร์เพื่อดึงข้อมูลประเภทที่คุณประกาศ ด้วยคำขอห้องสมุดมันง่ายที่จะส่ง POST:

import requests

url = "https://bugs.python.org"
data = {'@number': 12524, '@type': 'issue', '@action': 'show'}
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept":"text/plain"}
response = requests.post(url, data=data, headers=headers)

print(response.text)

เพิ่มเติมเกี่ยวกับคำขอวัตถุ: https://requests.readthedocs.io/en/master/api/


1

หากคุณไม่ต้องการใช้โมดูลที่คุณต้องติดตั้งrequestsและกรณีการใช้งานของคุณนั้นพื้นฐานมากคุณสามารถใช้งานได้urllib2

urllib2.urlopen(url, body)

โปรดดูเอกสารสำหรับurllib2ที่นี่: https://docs.python.org/2/library/urllib2.html

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