前言
最近想用 Python 自動地爬取某個站點里的圖片,沒想到其請求數據是以
request payload
格式傳輸給后端進行處理的。博主還是第一次遇到這種情況,寫下這篇文章記錄一下解決過程。
博主瀏覽器使用的是 Chrome,下文說的瀏覽器一律指的是 Chrome瀏覽器。
POST提交數據常見的幾種Content-Type
在網絡請求中常用的Content-Type有很多,但是在POST請求下我們常用的Content-Type大約有3種。
1.application/x-www-form-urlencoded
這應該是我們最常見到的POST數據提交方式,原生的表單默認提交方式就是這個,
我用站長工具模擬原生的POST請求,如圖1-1:
圖1-1
第一個紅框可以看到請求的
Content-Type
確實是
application/x-www-form-urlencoded
,第二個紅框展示的是向后端請求的數據,它是經過瀏覽器解碼然后展示給我們看的,實際上數據編碼格式如圖1-2:
可以看到,我們請求的數據變成了鍵值對的形式,并且中間用
&
分隔,形如
key1=val1&key2=val2
。
2.multipart/form-data
使用表單傳數文件時,Content-Type必須是
multipart/form-data
,傳輸的文件會被分割成多個部分,每部分使用–boundary分割。
大體如圖2-1:
第二個紅框數據也是經過瀏覽器解碼的,原始數據如圖2-2:
3.application/json
一般情況下,我們遇到的POST請求數據編碼格式都是
application/x-www-form-urlencoded
,但是這種格式有局限性,如果想向后端傳輸復雜的數據,如:
{
"info"
:
[
{
"name"
:
"Kelvin"
,
"age"
:
18
}
]
}
這個時候,采用
application/x-www-form-urlencoded
對數據進行編碼的話,就不是很方便。
對于像這種復雜的數據,一般都是以json格式直接傳給后端進行解析。
博主在爬蟲時遇到的就是
Content-Type:application/json
的情況,如圖3-1:
第二個紅框也不像前兩個一樣是
Form Data
而是變成了
Request Payload
,其中的數據也是經過瀏覽器解析的,原始數據如圖3-2:
可以看出來,數據確實是以json格式進行傳輸的。
如果我們想模擬這種請求,如下代碼是不行的:
import
requests
headers
=
{
'Content-Type'
:
'application/json'
,
.
.
.
.
.
.
}
data
=
{
"n"
:
"測試logo"
,
"s"
:
"TEST LOGO"
,
"descr"
:
"this is demo"
,
"data"
:
[
]
,
"p"
:
1
,
"dataPage"
:
0
,
"icon_lists"
:
[
]
,
"icon_page"
:
1
}
url
=
'https://www.logosc.cn/api/getAllInfo'
response
=
requests
.
post
(
url
=
url
,
data
=
data
,
headers
=
headers
)
print
(
response
.
json
(
)
)
根據請求的URL不同,報錯信息也會一樣,但無一例外的請求失敗,如圖3-3:
遇到Request Payload的解決辦法
碰到問題,我們首先求助的應該是官方文檔,文檔建議如下圖4-1:
圖4-1
官方提供了兩種方法讓我們以
application/json
格式編碼數據進行傳輸。
1.使用json.dumps()方法
json.dumps()方法將字典數據轉化成json類型然后傳給data參數,代碼如下:
import
requests
import
json
headers
=
{
'Content-Type'
:
'application/json'
,
.
.
.
.
.
.
}
data
=
{
"n"
:
"測試logo"
,
"s"
:
"TEST LOGO"
,
"descr"
:
"this is demo"
,
"data"
:
[
]
,
"p"
:
1
,
"dataPage"
:
0
,
"icon_lists"
:
[
]
,
"icon_page"
:
1
}
url
=
'https://www.logosc.cn/api/getAllInfo'
response
=
requests
.
post
(
url
=
url
,
data
=
json
.
dumps
(
data
)
,
headers
=
headers
)
print
(
response
.
json
(
)
)
2.將數據傳給json參數
requests.post方法里有個json參數,當我們把數據傳給json參數時,Content-Type會被自動的設置成application/json,代碼如下:
import
requests
headers
=
{
'Content-Type'
:
'application/json'
,
.
.
.
.
.
.
}
data
=
{
"n"
:
"測試logo"
,
"s"
:
"TEST LOGO"
,
"descr"
:
"this is demo"
,
"data"
:
[
]
,
"p"
:
1
,
"dataPage"
:
0
,
"icon_lists"
:
[
]
,
"icon_page"
:
1
}
url
=
'https://www.logosc.cn/api/getAllInfo'
response
=
requests
.
post
(
url
=
url
,
json
=
data
,
headers
=
headers
)
print
(
response
.
json
(
)
)
結尾語
今天又爬出了一個小坑,很是開心,如果本文對你有所幫助,歡迎關注下方公眾號「猿天罡」,不定期更新Python和算法相關的文章。see you!
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
