1. 程式人生 > >requests發送post請求的一些疑點

requests發送post請求的一些疑點

inorder androi ppr android key scrip 拼多多 寶寶 ajax

前言

在Python爬蟲中,使用requests發送請求,訪問指定網站,是常見的做法。一般是發送GET請求或者POST請求,對於GET請求沒有什麽好說的,而發送POST請求,有很多朋友不是很清楚,主要是因為容易混淆POST提交的方式。今天在微信交流群裏,就有朋友遇到了這種問題,特地講解一下。

在HTTP協議中,post提交的數據必須放在消息主體中,但是協議中並沒有規定必須使用什麽編碼方式,從而導致了提交方式的不同。服務端根據請求頭中的Content-Type字段來獲知請求中的消息主體是用何種方式進行編碼,再對消息主體進行解析。具體的編碼方式包括如下:

  • application/x-www-form-urlencoded:以form表單形式提交數據,最常見也是大家最熟悉的
  • application/json :以json串提交數據。
  • multipart/form-data:上傳文件

下面使用requests來發送上述三種編碼的POST請求。

1.提交Form表單

requests提交Form表單,一般存在於網站的登錄,用來提交用戶名和密碼。以http://httpbin.org/post 為例,在requests中,以form表單形式發送post請求,只需要將請求的參數構造成一個字典,然後傳給requests.post()的data參數即可。代碼如下:

url = ‘http://httpbin.org/post‘
d = {‘key1‘: ‘value1‘, ‘key2‘: ‘value2‘
} r = requests.post(url, data=d) print r.text

輸出效果如下:

{
"args":{},
"data":"",
"files":{},
"form":{"key1":"value1","key2":"value2"},
"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate",
"Connection":"close",
"Content-Length":"23",
"Content-Type":"application/x-www-form-urlencoded",
"Host":"httpbin.org",
"User-Agent":"python-requests/2.12.3"},
"json":null,
"origin":"113.140.11.122",
"url":"http://httpbin.org/post"}

httpbin.org網站可以顯示你提交請求的內容,大家註意一下輸出的"Content-Type":"application/x-www-form-urlencoded",證明這是提交Form的方式。大家在登錄一個網站時,可以觀察一下Content-Type是什麽。

2.提交json串

對於提交json串,主要是用於發送ajax請求中,動態加載數據。以拼多多網站為例,加載商品的方式為ajax,商品的內容在響應中。
技術分享圖片

下面把請求頭和請求實體列舉一下:

技術分享圖片
一些初學者根據請求頭寫爬蟲,就會犯requests的使用錯誤。

錯誤寫法

import requests

__author__ = ‘qiye‘
__date__ = ‘2018/5/19 21:59‘

url = "http://jinbao.pinduoduo.com/network/api/common/goodsList"
data ={"pageSize":60,"pageNumber":1,"withCoupon":0,"sortType":0}
headers = {
    ‘Content-Type‘:‘application/json; charset=UTF-8‘,
    ‘Host‘:‘jinbao.pinduoduo.com‘,
    ‘Origin‘:‘http://jinbao.pinduoduo.com‘,
    ‘Referer‘:‘http://jinbao.pinduoduo.com/‘,
    ‘User-Agent‘:‘Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36‘,
    ‘Accept‘: ‘application/json, text/javascript, */*; q=0.01‘,



}
r = requests.post(url=url,data =data,headers=headers)
print(r.text)

打印的內容如下:

{"success":false,"errorCode":4000000,"errorMsg":"System Error","result":null}

返回出錯了,這時候百思不得其解,請求頭我都保持一致了呀,‘Content-Type‘:‘application/json; charset=UTF-8‘都加上了,為什麽會出錯呀?
答案在於,你的請求實體的格式錯了,服務端無法解碼。

正確寫法1

正確代碼是把data進行json編碼,再發送。代碼如下:

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

這個時候再看一下打印內容,已經正確返回商品內容了。

{"success":true,"errorCode":1000000,"errorMsg":null,"result":{"total":2271278,"goodsList":[{"goodsId":998422995,"goodsName":"【4液+1器】皎潔電熱蚊香液 孕婦寶寶驅蚊兒童嬰無味防蚊液體","goodsImageUrl":"http://t11img.yangkeduo.com/images/2018-04-12/0292b5e75053dfa748b9762d3f3e74ef.jpeg","soldQuantity":175,"minGroupPrice":24890,"categoryId":4,"categoryName":"母嬰","hasCoupon":true,"couponMinOrderAmount":5000,"couponDiscount":5000,"couponTotalQuantity":5000,"couponRemainQuantity":3940,"couponStartTime":1526572800,"couponEndTime":1527782399,"promotionRate":280},
...

正確寫法2

處理將data主動編碼為json發送之外,requests還提供了一個json參數,自動使用json方式發送,而且在請求頭中也不用顯示聲明‘Content-Type‘:‘application/json; charset=UTF-8‘。完整代碼如下:

import requests

__author__ = ‘qiye‘
__date__ = ‘2018/5/19 21:59‘

url = "http://jinbao.pinduoduo.com/network/api/common/goodsList"
data ={"pageSize":60,"pageNumber":1,"withCoupon":0,"sortType":0}
headers = {
    ‘Host‘:‘jinbao.pinduoduo.com‘,
    ‘Origin‘:‘http://jinbao.pinduoduo.com‘,
    ‘Referer‘:‘http://jinbao.pinduoduo.com/‘,
    ‘User-Agent‘:‘Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36‘,
}
r = requests.post(url=url,json =data,headers=headers)
print(r.text)

3.上傳文件

上傳文件在爬蟲中使用的很少,不過還是使用requests講解一下使用方式。Content-Type類型為multipart/form-data,以multipart形式發送post請求,只需將一文件傳給requests.post()的files參數即可。還是以http://httpbin.org/post 為例,代碼如下:

url = ‘http://httpbin.org/post‘
files = {‘file‘: open(‘upload.txt‘, ‘rb‘)}
r = requests.post(url, files=files)
print(r.text)

4.福利大放送

關註公眾號:七夜安全博客
技術分享圖片

  • 回復【1】:領取 Python數據分析 教程大禮包
  • 回復【2】:領取 Python Flask 全套教程
  • 回復【3】:領取 某學院 機器學習 教程
  • 回復【4】:領取 爬蟲 教程

知識星球已經30多人了,隨著人數的增多,價格之後會上漲,越早關註越多優惠。星球的福利有很多:

  • 比如上面的教程,已經提前在知識星球中分享
  • 可以發表一些問題,大家一塊解決
  • 我之後寫的電子書,錄制的教學視頻,對於知識星球的朋友都是優惠的(基本上免費)
  • 一些節假日會給大家發個紅包或者贈書

技術分享圖片

requests發送post請求的一些疑點