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里大整数相乘相关技巧指南
Sep 12 Python
python实现可将字符转换成大写的tcp服务器实例
Apr 29 Python
Python中转换角度为弧度的radians()方法
May 18 Python
Python按行读取文件的简单实现方法
Jun 22 Python
详解Python读取yaml文件多层菜单
Mar 23 Python
python 缺失值处理的方法(Imputation)
Jul 02 Python
Django多数据库的实现过程详解
Aug 01 Python
python读取当前目录下的CSV文件数据
Mar 11 Python
如何查看Django ORM执行的SQL语句的实现
Apr 20 Python
解决在keras中使用model.save()函数保存模型失败的问题
May 21 Python
深入理解Python 多线程
Jun 16 Python
python实现图片批量压缩
Apr 24 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
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
PHP+Jquery与ajax相结合实现下拉淡出瀑布流效果【无需插件】
2016/05/06 PHP
thinkphp中U方法按路由规则生成url的方法
2018/03/12 PHP
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
js遍历td tr等html元素
2012/12/13 Javascript
jQuery中end()方法用法实例
2015/01/08 Javascript
有关easyui-layout中的收缩层无法显示标题的解决办法
2016/05/10 Javascript
jquery过滤特殊字符',防sql注入的实现方法
2016/08/17 Javascript
在百度搜索结果中去除掉一些网站的资料(通过js控制不让显示)
2017/05/02 Javascript
vue.js的安装方法
2017/05/12 Javascript
Vue实现动态显示textarea剩余字数
2017/05/22 Javascript
node.js将MongoDB数据同步到MySQL的步骤
2017/12/10 Javascript
简单谈谈CommonsChunkPlugin抽取公共模块
2017/12/31 Javascript
一个简单的node.js界面实现方法
2018/06/01 Javascript
jQuery实现简单复制json对象和json对象集合操作示例
2018/07/09 jQuery
springMvc 前端用json的方式向后台传递对象数组方法
2018/08/07 Javascript
jQuery实现上下滚动公告栏详细代码
2018/11/21 jQuery
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
2019/09/23 Javascript
node解析修改nginx配置文件操作实例分析
2019/11/06 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
2020/09/24 Javascript
vue实现登录功能
2020/12/31 Vue.js
python使用WMI检测windows系统信息、硬盘信息、网卡信息的方法
2015/05/15 Python
Python基于pandas实现json格式转换成dataframe的方法
2018/06/22 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
德国圣伯纳德草药屋:Kräuterhaus Sanct Bernhard(有中文站)
2018/08/05 全球购物
C++面试题目
2013/06/25 面试题
情人节活动策划方案
2014/02/27 职场文书
爱心捐书活动总结
2014/07/05 职场文书
科级干部群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
部队反四风对照检查材料
2014/09/26 职场文书
社区综治工作汇报
2014/10/27 职场文书
2014年领导班子工作总结
2014/12/11 职场文书
2015年美容师个人工作总结
2015/10/14 职场文书
Python基础之pandas数据合并
2021/04/27 Python