爬虫小记:POST请求之 multipart/form-data 类型
某次开发时发现模拟一个 post 请求不下来数据,然后发现 Content-Type 是 multipart/form-data; boundary=----WebKitFormBoundaryEeshAWrJZZFlx0QB 类型的不同于以前常用的的 text/plain 和 application/x-www-form-urlencoded 因此记录下。
1.Content-Type类型
Content-Type 解释为请求的与实体对应的MIME信息,作用是指定处理请求的提交内容类型 ,比如文本格式、图片格式、二进制格式。
2.常见的媒体格式类型
-
text/html : HTML格式 text/plain :纯文本格式 application/octet-stream : 二进制流数据(如常见的文件下载) application/x-www-form-urlencoded : <form encType="">中默认的 encType,form 表单数据被编码为 **key/value **格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
-
multipart/form-data : 需要在表单中进行文件上传(图片、MP3、文件)时,就需要使用该格式
3.解决方法
- 通过模拟参数生成的方式来请求,这种方法完全是逆着来的方式去还原参数,我们需要先手动获得 Content-Type 中 boundary 的参数
- 然后先观察格式化的请求表单的key-value,按照顺序构建有序字典。
- 最后模拟请求百度替换上边获得的 boundary 参数,之后得到的就是下边源码形式。
- 关键代码如下
from collections import OrderedDict
headers = {
accept: */*,
accept-encoding: gzip, deflate, br,
accept-language: zh-CN,zh;q=0.9,
cache-control: no-cache,
content-type: multipart/form-data; boundary=----WebKitFormBoundaryEeshAWrJZZFlx0QB,
pragma: no-cache,
sec-fetch-dest: empty,
sec-fetch-mode: cors,
sec-fetch-site: same-origin,
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36
}
# 构建表单生成的参数
params = OrderedDict([("filter",(None,
{"must":[{"operStatus_v2":[{"eq":[["营业"]]}]},{"hasMobile":[{"exist":"1"}]},{"name":[{"in":["进出口","国际贸易"]}]},{"name":[{"nin":["服务部","代理中心","服务中心","服务处","代理站","代理店","代理点","服务点","服务站","代理行","营业部","代理部","服务店","咨询部","经营部","运营部","经部","代理商行","代理处","商行","项目点","服务行"]}]},{"address":[{"eq":[["广东"]]}]}]}, multipart/form-data)),
("relation",(None, 0, multipart/form-data)),
("start",(None, f{start}, multipart/form-data)),
("end",(None, f{end}, multipart/form-data)),
("filter_advance_search_filter_pool",(None, 1, multipart/form-data)),
("mode",(None, 2, multipart/form-data)),])
res = requests.get(http://www.baidu.com, files=params)
temp = re.search(r--(.*)--, str(res.request.body.decode(utf-8))).group(1)
data = re.sub(temp, ----WebKitFormBoundaryEeshAWrJZZFlx0QB, res.request.body.decode(utf-8))
response = requests.post(url, headers=headers, data=data.encode("utf-8"), verify=False, timeout=15)
