Python发送form-data请求及拼接form-data内容的方法


Posted in Python onMarch 05, 2016

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

ulrlib2 的模拟post方法,如下:

import urllib2

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

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

问题就出在    '\r\n'.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:\Users\danwang3\Desktop\libmsc.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:\Users\danwang3\Desktop\libmsc.zip','rb'),'application/x-zip-compressed')
 }

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

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

就这么简单

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

files = {'name': (<filename>, <file object>,<content type>, <per-part headers>)}

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

Content-Disposition: form-data; name='name';filename=<filename>
Content-Type: <content type>
 
<file object>
--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内容

#!\urs\bin\env 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('0123456789abcdef', 15)) 
  CRLF = '\r\n' 
  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','489'),("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方法就可以发送了。

Python 相关文章推荐
Python学习笔记(二)基础语法
Jun 06 Python
详解Python中用于计算指数的exp()方法
May 14 Python
Python基于Tkinter实现的记事本实例
Jun 17 Python
Python实现微信消息防撤回功能的实例代码
Apr 29 Python
详解Python3之数据指纹MD5校验与对比
Jun 11 Python
简单了解python 生成器 列表推导式 生成器表达式
Aug 22 Python
Django和Flask框架优缺点对比
Oct 24 Python
有关Tensorflow梯度下降常用的优化方法分享
Feb 04 Python
Python递归调用实现数字累加的代码
Feb 25 Python
python中np是做什么的
Jul 21 Python
Python selenium爬取微信公众号文章代码详解
Aug 12 Python
Pandas DataFrame求差集的示例代码
Dec 13 Python
Python多线程爬虫简单示例
Mar 04 #Python
使用Python来开发Markdown脚本扩展的实例分享
Mar 04 #Python
使用py2exe在Windows下将Python程序转为exe文件
Mar 04 #Python
用Python编写简单的微博爬虫
Mar 04 #Python
python相似模块用例
Mar 04 #Python
Python程序中用csv模块来操作csv文件的基本使用教程
Mar 03 #Python
举例简单讲解Python中的数据存储模块shelve的用法
Mar 03 #Python
You might like
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
PHP mail()函数使用及配置方法
2014/01/14 PHP
php读取csv文件并输出的方法
2015/03/14 PHP
浅谈本地WAMP环境的搭建
2015/05/13 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
2016/01/09 PHP
浅谈PHP中静态方法和非静态方法的相互调用
2016/10/04 PHP
jQuery使用手册之一
2007/03/24 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
node.js入门教程
2014/06/01 Javascript
jQuery事件绑定和委托实例
2014/11/25 Javascript
实例代码讲解jquery easyui动态tab页
2015/11/17 Javascript
理解JavaScript中worker事件api
2015/12/25 Javascript
BootStrap下jQuery自动完成的样式调整
2016/05/30 Javascript
jQuery模仿单选按钮选中效果
2016/06/24 Javascript
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
详解webpack 入门与解析
2018/04/09 Javascript
JavaScript 严格模式(use strict)用法实例分析
2020/03/04 Javascript
Array.filter中如何正确使用Async
2020/11/04 Javascript
[52:52]完美世界DOTA2联赛PWL S3 LBZS vs access 第一场 12.10
2020/12/13 DOTA
Python中datetime模块参考手册
2017/01/13 Python
Python中 CSV格式清洗与转换的实例代码
2019/08/29 Python
Python基于jieba, wordcloud库生成中文词云
2020/05/13 Python
Html5内唤醒百度、高德APP的实现示例
2019/05/20 HTML / CSS
名人珠宝设计师:Melinda Maria Jewelry
2019/03/06 全球购物
请介绍一下Ant
2016/07/22 面试题
在浏览器端如何得到服务器端响应的XML数据
2012/11/24 面试题
值传递还是引用传递
2015/02/08 面试题
初中生个人学习的自我评价
2013/12/04 职场文书
历史教育专业个人求职信
2013/12/13 职场文书
电子专业自荐信
2014/07/01 职场文书
地质工程专业毕业生求职信
2014/08/08 职场文书
公安局负责人查摆问题及整改方案
2014/09/27 职场文书
纪委书记群众路线整改措施思想汇报
2014/10/09 职场文书
大学生个人学年总结
2015/02/15 职场文书
酒店厨房管理制度
2015/08/06 职场文书
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js