Python写自动化之构造Multipartform-data发请求

在HTTP协议的规范中会将http请求分为三个部分:状态行,请求头,请求体。在发送HTTP请求时,需要在请求头中注明发送的方法,这些方法包括:OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT。其中GET和POST是最为普遍被使用的。有关POST和GET的区别,知识库中已经有同学进行了表述,这里主要介绍一下multipart/form-data请求具体是怎么一回事。

在普通的HTML Form Post请求中,它会在头信息里使用Content-Length注明内容长度。头信息每行一条,空行之后便是Body,即“内容”(entity)。它的Content-Type是application/x-www-form-urlencoded,这意味着消息内容会经过URL编码,就像在GET请求时URL里的QueryString那样。以搜狗浏览器扩展升级的请求为例:

在早期的HTTP Post是不支持文件上传的,编程开发带来很多问题。所以在《RFC 1867 -Form-based File Upload in HTML》中增加了用以支持文件上传的类型。即Content-Type的类型扩充了multipart/form-data用以支持向服务器发送二进制数据。因此发送post请求时,表单<form>属性enctype共有二个值可选,这个属性管理的是表单的MIME编码:

  1. application/x-www-form-urlencoded(默认值)
  2. multipart/form-data

其实form表单在你不写enctype属性时,也默认为其添加了enctype属性值,默认值是enctype="application/x- www-form-urlencoded".

那么multipart/form-data请求有哪些特征呢?

1、multipart/form-data的基础方法是post

2、multipart/form-data与普通post方法的不同之处:请求头,请求体。

3、multipart/form-data的请求头必须包含一个特殊的头信息:Content-Type,且其值也必须规定为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中的多个post的内容,如文件内容和文本内容自然需要分割开来,不然接收方就无法正常解析和还原这个文件了。

4、multipart/form-data的请求体也是一个字符串,不过和普通post的请求体不同的是它的构造方式,post是简单的name=value值连接,而multipart/form-data则是添加了分隔符等内容的构造体。

通过Fiddler截取发送的请求包内容如图:

本次12306预约抢票功能的测试过程中,在针对“提交预约单”的接口进行测试时,客户端向服务端提交信息的方式就是multipart/form-data。为了提高测试效率,便利用Python构造网络请求来针对接口进行了测试。具体的代码如下:

# coding=gbk

import urllib2;

import json;

def post_data():

    parameters = {'id': '', 'user': { 'username': '', 'password': '' }, 'query': { 'fromStation': 'beijing', 'fromStationText': 'shanghai' }}

    jdata = json.dumps( parameters )

    post_multipart( 'http://extention.ie.sogou.com/mm_12306/prebook', jdata )

def post_multipart( url , fields ):

    content_type, body = encode_multipart_formdata( "data", fields )

    req = urllib2.Request( url, body )

    req.add_header( "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 SE 2.X MetaSr 1.0)" )

    req.add_header( "Accept", "*/*" )

    req.add_header( "Accept-Language", "zh-CN,zh;q=0.8" )

    req.add_header( "Accept-Encoding", "gzip,deflate,sdch" )

    req.add_header( "Connection", "keep-alive" )

    req.add_header( "Content-Type", content_type )

    req.add_header( "User-Agent1", "SogouMSE" )

    try:

        response = urllib2.urlopen( req )

        the_page = response.read().decode( 'utf-8' )

        print the_page

        return the_page

    except urllib2.HTTPError, e:

        print e.code

        pass

    except urllib2.URLError, e:

        print str( e )

        pass

def encode_multipart_formdata( key, value ):

    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'

    CRLF = '\r\n'

    L = []

    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

if __name__ == '__main__':

    post_data();
时间: 2024-10-13 03:14:34

Python写自动化之构造Multipartform-data发请求的相关文章

Python写自动化之写一个Windows 服务

Python 写windows 服务,需要使用 pywin32包. 直接上代码: #encoding=utf8 ''' Created on 2014-7-1 @author: wangmengnan ''' import os import sys import win32serviceutil import win32service import win32event class PythonService(win32serviceutil.ServiceFramework): #服务名 _

Python写自动化之logging日志写入

日志写入是我们日常工作中常用到的功能,我们可以直接使用写文件的方式来以自己的方式写日志,另外,当我们在一个比较大的项目中,涉及到日志写入时,一般会使用logging模块来进行日志的写入,第一步,先写一个单例,创建一个logger对象: def _instance(): global logger if logger is None: logging.config.fileConfig(os.path.join(util.get_current(), "logger.conf")) lo

python接口自动化(四十一)- 发xml格式参数的post请求(超详解)

简介 最近在工作中,遇到一种奇葩的接口,它的参数数据是通过xml,进行传递的,不要大惊小怪的,林子大了什么鸟都有,每个人的思路想法不一样,开发的接口也是各式各样的,如果想要统一的话,必须是提前团队已经做好沟通定好规则,这样就像在产品线上生成一 样规格大小一致.就不会出现前边的问题了,如果出现了怎么办?而且项目进度比较急,没有时间修改,一期上线就只能凑合着用这组接口了,那么作为QA的你,会不会测试,如何用代码.工具实现呢???等等问题跟着就产生了. 前边就有介绍到有关:post请求相对于get请求

Python写自动化之启动进程并获取进程输出

当我们需要执行外部命令或自己写一个自动化执行器时,需要使用到启动进程并获取输出的操作 首先,我们启动进程采用Python的subprocess模块,为了保证标准输出和标准错误输出能够正常运行,启动两个线程来检测输出结果部分 class Daemon(threading.Thread): def __init__(self, workDir, logFunction=None, *args): threading.Thread.__init__(self) self.process = None

Python写自动化之邮件发送(匿名)

为了能够实现邮件发送功能,首先,我们需要了解一下邮件的发送过程是什么样子的,此处不再详细说明,请大家自行搜索或查看http://www.sogouqa.com/?p=438 在了解了邮件的发送过程后,为了实现邮件的全自动匿名发送,我们需要通过windows的命令行,解析邮件的匿名服务器,然后使用匿名服务器,发送邮件到相应的邮箱 代码如下: def _get_mail_exchanger(domain_name,name_server=""): #print domain_name te

Python写自动化之ini文件的读写

在我们写一些测试工具时,经常会需要使用到配置文件,此时一般选用ini文件是比较合适的 标准并且可以通过参数命名知道参数的含义,那么使用Python如何进行ini文件的读写呢? 首先看下,读取ini文件,我们直接使用Python自带的模块ConfigParser来进行配置文件的读写 看下代码吧 def ReadConfig(configPath): configDict = {} cf = ConfigParser.ConfigParser() cf.read(configPath) sessio

Python写自动化之获取文件的MD5值

使用Python 获取文件的MD5 值是一件很简单的事情,Python 提供了md5 和 hashlib 两个模块,都可以获取到文件的md5值. 代码如下: #获取文件的MD5值,适用于小文件 def getFileMD5(self,filepath): if self.isFile(filepath): f = open(filepath,'rb') md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest()

Python写自动化之SVN更新

在远程机器上执行脚本时,为了能够保证脚本的实时性,我们一般会将脚本存放到SVN上,远程机器通过SVN的操作去更新脚本: SVN更新脚本只需要2步就可以实现了,这个地方使用到pysvn库,看下实现 # 初始化client self.client = pysvn.Client() self.client.set_default_username(self.username) self.client.set_default_password(util.decrypt_des(self.password

Python写自动化之图标锁定到任务栏或删除图标

这个功能在windows上测试安装卸载时,有时会用到,网上查到的两种语言的版本如下: C#版: Shell shell = new Shell(); Folder folder = shell.NameSpace(Path.GetDirectoryName(appPath)); FolderItem app = folder.ParseName(Path.GetFileName(appPath)); string sVerb = isLock ? "锁定到任务栏(&K)" :