網絡爬蟲-使用requests上傳multipart/form-data格式文件

由於以前沒有使用requests上傳過文件,所以今天在使用它上傳文件的時候遇見了一個坑,接下來我們就來一層一層解析這個坑

科大訊飛官網上傳音頻文件爲例

首先是喜聞樂見地打開Fiddler進行抓包操作,流程也很簡單,很快就抓下來了上傳文件的這個包,見下圖

在這裏插入圖片描述

然後就進入了懵逼模式,content-type裏面這個boundary是啥,以前咋沒見過呢,還有data裏面的這些個東西又是啥,還來亂碼了,奇怪了奇怪了,於是去翻閱了資料。

根據http/1.1 rfc 2616的協議規定,我們的請求方式只有OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE等,那爲爲何我們還會有multipart/form-data請求之說呢?這就要從頭來說了。

http協議規定以ASCII碼傳輸,建立在tcp,ip協議智商的引用規範,規範內容把http請求分成3個部分,狀態行,請求頭,請求體。所有的方法,實現都是圍繞如何使用和組織這三部分來完成了,萬變不離其宗,http的知識大家可以問度娘。

既然上面請求方式裏面沒有multipart/form-data那這個請求又是怎麼回事呢,其實是一回事,multipart/form-data也是在post基礎上演變而來的,具體如下:

1.multipart/form-data的基礎方式是post,也就是說通過post組合方式來實現的。
2.multipart/form-data於post方法的不同之處在於請求頭和請求體。
3.multipart/form-data的請求頭必須包含一個特殊的頭信息:Content-Type,其值也必須爲multipart/form-data,同時還需要規定一個內容分割用於分割請求提中多個post的內容,如文件內容和文本內容是需要分隔開來的,不然接收方就無法解析和還原這個文件了,具體的頭信息如下:

Content-Type: multipart/form-data; boundary=${bound}

參考 什麼是multipart/form-data請求

然後美滋滋地直接用requests去上傳了一波文件

import requests
 
url = 'https://www.iflyrec.com/XFTJService/web/audio/upload?folder=1416861992900653'
files = {'file': open('video.wav', 'rb')}
 
r = requests.post(url, files=files)
print(r.text)

好的 然後毫無疑問地報錯

在這裏插入圖片描述

話說這不應該啊 不是在我想象中這樣就應該OK了麼 於是硬着頭皮再面向百度了一波–

具體參考的這篇博文 使用python的requests 發送multipart/form-data 請求

然後參考了我抓的包,發現multipart/form-data 請求在requests裏面其實是有實例的,使用元組形式上傳files,於是完成了以下代碼

import requests

headers = {
    "Host": "www.iflyrec.com",
    "Connection": "keep-alive",
    "Content-Length": "137110",
    "Origin": "https://www.iflyrec.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6776.400 QQBrowser/10.3.2601.400",
    "Accept": "*/*",
    "Referer": "https://www.iflyrec.com/html/addArtificialOrder.html",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9",
    # "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryZjPRjN0wAzGytw34",
    "Cookie": "login_err=0; from=baidu; keywords=%25e8%25ae%25af%25e9%25a3%259e+%25e8%25af%25ad%25e9%259f%25b3%25e8%25af%2586%25e5%2588%25ab; Hm_lvt_aee4c3bed3d9924f2f184904ecb37065=1542615755; Hm_lvt_c711619f2461980a3dbceed5874b0c6a=1542615755; storage=QsIwv8WBIrqRiBa62wvKbo8oswgQSz4Wr4bjQk8jm+scRW7Z6rVZZv1WwElHU0BN+ZAmvzlXvxc2gaeHLi2yHQ==; ec_im_local_status=0; CUSTOM_INVITE_CONTENT=; ec_invite_state=0; Hm_lpvt_aee4c3bed3d9924f2f184904ecb37065=1542615766; ec_im_tab_num=1; ec_invite_state_time=1542615765582; Hm_lpvt_c711619f2461980a3dbceed5874b0c6a=1542615766"
}

# files = {'file': open('333.wav', 'rb')}

files = {'id': (None, 'WU_FILE_0'), 
         'name':  (None, '333.wav'), 
         'type': (None, 'audio/wav'),
         'lastModifiedDate': (None, 'Tue Aug 21 2018 17:22:12 GMT+0800 (中國標準時間)'),
         'size': (None,'136380'), 
         'file': ('333.wav', open('333.wav', 'rb'), 'audio/wav')} # 

r = requests.post('https://www.iflyrec.com/XFTJService/web/audio/upload?folder=1416861992900653', headers=headers, files=files)

print(r.text)
print(r.headers)
print(r.status_code)

運行成功圖如下

在這裏插入圖片描述

需要注意的是,我將headers請求頭裏面的content-type屬性註釋了,如果加上了,則會報錯,然後我把這個模擬請求抓包下來看了看,他自動加上了Content-Type: multipart/form-data; boundary=${bound},所以這個boundary應該是上傳文件的標識,上傳文件的時候content-type會有一個默認值,我們不去指定,也就沒問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章