视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python发送form-data请求及拼接form-data内容的方法
2020-11-27 14:35:39 责编:小采
文档


网上关于使用python 的发送multipart/form-data的方法,多半是采用

ulrlib2 的模拟post方法,如下:

import urllib2

boundary='-------------------------7df3069603d6' 
data=[] 
data.append('--%s' % boundary) 
data.append('Content-Disposition: form-data; name="app_id"
') 
data.append('xxxxxx') 
data.append('--%s' % boundary) 
data.append('Content-Disposition: form-data; name="version"
') 
data.append('xxxxx') 
data.append('--%s' % boundary) 
data.append('Content-Disposition: form-data; name="platform"
') 
data.append('xxxxx') 
data.append('--%s' % boundary) 
data.append('Content-Disposition: form-data; name="libzip"; filename="C:Usersdanwang3Desktoplibmsc.zip"') 
data.append('Content-Type: application/octet-stream
') 
 
fr=open('C:Usersdanwang3Desktoplibmsc.zip') 
content=fr.read() 
data.append(content) 
print content 
fr.close() 
data.append('--%s--
'%boundary) 
httpBody='
'.join(data) 
 
print type(httpBody) 
print httpBody 
 
postDataUrl='http://xxxxxxxx' 
req=urllib2.Request(postDataUrl,data=httpBody) 

经过测试,使用上述方法发送一段二进制文件的时候,服务器报错,数据有问题!

问题就出在 ' '.join(data)的编码,data内部拥有二进制数据,通过这种编码,可能是把数据转换为utf-8格式,当然有问题。

搜索了很多资料,查到可以使用requests库提交multipart/form-data 格式的数据

一个multipart/form-data 的表单数据,在http里面抓包如下:

#Content-Disposition: form-data;name="app_id"


 123456

#-----------------------------7df23df2a0870

#Content-Disposition: form-data;name="version"

 

 2256

 -----------------------------7df23df2a0870

 Content-Disposition:form-data; name="platform"

 

 ios

 -----------------------------7df23df2a0870

 Content-Disposition: form-data;name="libzip";filename="C:Usersdanwang3Desktoplibmsc.zip"

 Content-Type: application/x-zip-compressed

<二进制文件数据未显示>

 ---------------------------7df23df2a0870—


上述数据在requests里面可以模拟为:

files={'app_id':(None,'123456'),
 'version':(None,'2256'),
 'platform':(None,'ios'),
 'libzip':('libmsc.zip',open('C:Usersdanwang3Desktoplibmsc.zip','rb'),'application/x-zip-compressed')
 }

发送上述post请求,也就是简单的

response=requests.post(url,files=files)

就这么简单

在官方网站上,requests模拟一个表单数据的格式如下:

files = {'name': (, ,, )}

这一行模拟出来的post数据为:

Content-Disposition: form-data; name='name';filename=
Content-Type: 
 

--boundary

如果filename 和 content-Type不写,那么响应模拟post的数据就不会有二者。

通常使用requests 不像使用urllib2那样可以自动管理cookie,不过如果获取到cookie

可以在requests请求里面一并将cookie发送出去

requests使用的cookie格式如下:

newCookie={}
newCookie['key1']='value1'
newCookie['key2]='value2'
newCookie['key3']='value3'


发送cookie可以使用:

response=requests.post(url,cookies=newCookie)

这样就可以了

拼接form-data的post内容

#!ursinenv python 
#encoding:utf-8 #设置编码方式 
 
from http2 import http 
import urllib 
 
def ReadFileAsContent(filename): 
 #print filename 
 try: 
 with open(filename, 'rb') as f: 
 filecontent = f.read() 
 except Exception, e: 
 print 'The Error Message in ReadFileAsContent(): ' + e.message 
 return '' 
 return filecontent 
 
 
def get_content_type(filename): 
 import mimetypes 
 return mimetypes.guess_type(filename)[0] or 'application/octet-stream' 
 
def isfiledata(p_str): 
 import re 
 
 r_c = re.compile("^f'(.*)'$") 
 rert = r_c.search(str(p_str)) 
 #rert = re.search("^f'(.*)'$", p_str) 
 if rert: 
 return rert.group(1) 
 else: 
 return None 
 
def encode_multipart_formdata(fields): 
 ''''' 
 该函数用于拼接multipart/form-data类型的http请求中body部分的内容 
 返回拼接好的body内容及Content-Type的头定义 
 ''' 
 import random 
 import os 
 BOUNDARY = '----------%s' % ''.join(random.sample('01234567abcdef', 15)) 
 CRLF = '
' 
 L = [] 
 for (key, value) in fields: 
 filepath = isfiledata(value) 
 if filepath: 
 L.append('--' + BOUNDARY) 
 L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, os.path.basename(filepath))) 
 L.append('Content-Type: %s' % get_content_type(filepath)) 
 L.append('') 
 L.append(ReadFileAsContent(filepath)) 
 else: 
 L.append('--' + BOUNDARY) 
 L.append('Content-Disposition: form-data; name="%s"' % key) 
 L.append('') 
 L.append(value) 
 L.append('--' + BOUNDARY + '--') 
 L.append('') 
 body = CRLF.join(L) 
 content_type = 'multipart/form-data; boundary=%s' % BOUNDARY 
 return content_type, body 

其中需要注意的是文件数据的字典值,其格式为f'/path/to/file',具体调用的形式如下:

form_data = [('gShopID','4'),("addItems", r"f'D:case3guomei.xml'"), ('validateString', '92c99a2a36f47c6aa2f0019caa0591d2')] 
form_data_re = encode_multipart_formdata(form_data) 
print form_data_re 

返回的内容是一个元组,第一个参数是请求头中Content-Type的值,第二个是具体post的内容。然后使用httplib的post方法就可以发送了。

下载本文
显示全文
专题