Python requests发送post请求的一些疑点


Posted in Python onMay 20, 2018

前言

在Python爬虫中,使用requests发送请求,访问指定网站,是常见的做法。一般是发送GET请求或者POST请求,对于GET请求没有什么好说的,而发送POST请求,有很多朋友不是很清楚,主要是因为容易混淆 POST提交的方式 。今天在微信交流群里,就有朋友遇到了这种问题,特地讲解一下。

在HTTP协议中,post提交的数据必须放在消息主体中,但是协议中并没有规定必须使用什么编码方式,从而导致了 提交方式 的不同。服务端根据请求头中的 Content-Type 字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析。具体的编码方式包括如下:

  1. application/x-www-form-urlencoded:以form表单形式提交数据,最常见也是大家最熟悉的
  2.  application/json :以json串提交数据。

下面使用requests来发送上述三种编码的POST请求。

1.提交Form表单

requests提交Form表单,一般存在于网站的登录,用来提交用户名和密码。以http://httpbin.org/post 为例,在requests中,以form表单形式发送post请求,只需要将请求的参数构造成一个字典,然后传给requests.post()的data参数即可。代码如下:

url = 'http://httpbin.org/post'
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, data=d)
print r.text

输出效果如下:

{
"args":{},
"data":"",
"files":{},
"form":{"key1":"value1","key2":"value2"},
"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate",
"Connection":"close",
"Content-Length":"23",
"Content-Type":"application/x-www-form-urlencoded",
"Host":"httpbin.org",
"User-Agent":"python-requests/2.12.3"},
"json":null,
"origin":"113.140.11.122",
"url":http://httpbin.org/post}

httpbin.org网站可以显示你提交请求的内容,大家注意一下输出的"Content-Type":"application/x-www-form-urlencoded",证明这是提交Form的方式。大家在登录一个网站时,可以观察一下Content-Type是什么。

2.提交json串

对于提交json串,主要是用于发送ajax请求中,动态加载数据。以拼多多网站为例,加载商品的方式为ajax,商品的内容在响应中。

Python requests发送post请求的一些疑点

下面把请求头和请求实体列举一下:

Python requests发送post请求的一些疑点 

一些初学者根据请求头写爬虫,就会犯requests的使用错误。

错误写法

import requests
__author__ = 'qiye'
__date__ = '2018/5/19 21:59'

url = "http://jinbao.pinduoduo.com/network/api/common/goodsList"
data ={"pageSize":60,"pageNumber":1,"withCoupon":0,"sortType":0}
headers = {
  'Content-Type':'application/json; charset=UTF-8',
  'Host':'jinbao.pinduoduo.com',
  'Origin':'http://jinbao.pinduoduo.com',
  'Referer':'http://jinbao.pinduoduo.com/',
  'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36',
  'Accept': 'application/json, text/javascript, */*; q=0.01',
}
r = requests.post(url=url,data =data,headers=headers)
print(r.text)

打印的内容如下:

{"success":false,"errorCode":4000000,"errorMsg":"System Error","result":null}

返回出错了,这时候百思不得其解,请求头我都保持一致了呀,'Content-Type':'application/json; charset=UTF-8'都加上了,为什么会出错呀?

答案在于,你的请求实体的格式错了,服务端无法解码。

正确写法1

正确代码是把data进行json编码,再发送。代码如下:

r = requests.post(url=url,data =json.dumps(data),headers=headers)

这个时候再看一下打印内容,已经正确返回商品内容了。

{"success":true,"errorCode":1000000,"errorMsg":null,"result":{"total":2271278,"goodsList":[{"goodsId":998422995,"goodsName":"【4液+1器】皎洁电热蚊香液 孕妇宝宝驱蚊儿童婴无味防蚊液体","goodsImageUrl":"http://t11img.yangkeduo.com/images/2018-04-12/0292b5e75053dfa748b9762d3f3e74ef.jpeg","soldQuantity":175,"minGroupPrice":24890,"categoryId":4,"categoryName":"母婴","hasCoupon":true,"couponMinOrderAmount":5000,"couponDiscount":5000,"couponTotalQuantity":5000,"couponRemainQuantity":3940,"couponStartTime":1526572800,"couponEndTime":1527782399,"promotionRate":280},
...

正确写法2

处理将data主动编码为json发送之外,requests还提供了一个json参数,自动使用json方式发送,而且在请求头中也不用显示声明'Content-Type':'application/json; charset=UTF-8'。完整代码如下:

import requests

__author__ = 'qiye'
__date__ = '2018/5/19 21:59'

url = "http://jinbao.pinduoduo.com/network/api/common/goodsList"
data ={"pageSize":60,"pageNumber":1,"withCoupon":0,"sortType":0}
headers = {
  'Host':'jinbao.pinduoduo.com',
  'Origin':'http://jinbao.pinduoduo.com',
  'Referer':'http://jinbao.pinduoduo.com/',
  'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36',
}
r = requests.post(url=url,json =data,headers=headers)
print(r.text)

3.上传文件

上传文件在爬虫中使用的很少,不过还是使用requests讲解一下使用方式。Content-Type类型为multipart/form-data,以multipart形式发送post请求,只需将一文件传给requests.post()的files参数即可。还是以http://httpbin.org/post 为例,代码如下:

url = 'http://httpbin.org/post'
files = {'file': open('upload.txt', 'rb')}
r = requests.post(url, files=files)
print(r.text)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
详解Django通用视图中的函数包装
Jul 21 Python
python daemon守护进程实现
Aug 27 Python
利用 python 对目录下的文件进行过滤删除
Dec 27 Python
pytorch 调整某一维度数据顺序的方法
Dec 08 Python
Python实现图片转字符画的代码实例
Feb 22 Python
Django项目主urls导入应用中views的红线问题解决
Aug 10 Python
pytorch 实现cross entropy损失函数计算方式
Jan 02 Python
jupyter notebook 增加kernel教程
Apr 10 Python
Python使用plt.boxplot() 参数绘制箱线图
Jun 04 Python
10行Python代码实现Web自动化管控的示例代码
Aug 14 Python
Pytorch1.5.1版本安装的方法步骤
Dec 31 Python
Elasticsearch 数据类型及管理
Apr 19 Python
python中virtualenvwrapper安装与使用
May 20 #Python
django静态文件加载的方法
May 20 #Python
django中静态文件配置static的方法
May 20 #Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
May 19 #Python
Python利用公共键如何对字典列表进行排序详解
May 19 #Python
Python中一些不为人知的基础技巧总结
May 19 #Python
Python + selenium自动化环境搭建的完整步骤
May 19 #Python
You might like
php采集文章中的图片获取替换到本地(实现代码)
2013/07/08 PHP
PHP判断文件是否被引入的方法get_included_files用法示例
2016/11/29 PHP
laravel migrate初学常见错误的解决方法
2017/10/11 PHP
用javascript实现的支持lrc歌词的播放器
2007/05/17 Javascript
JQuery Study Notes 学习笔记(一)
2010/08/04 Javascript
关于递归运算的顺序测试代码
2011/11/30 Javascript
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
Bootstrap的图片轮播示例代码
2015/08/31 Javascript
JS实现同一个网页布局滑动门和TAB选项卡实例
2015/09/23 Javascript
超实用的JavaScript表单代码段
2016/02/26 Javascript
JavaScript判断页面加载完之后再执行预定函数的技巧
2016/05/17 Javascript
js学习之----深入理解闭包
2016/11/21 Javascript
js仿iphone秒表功能 计算平均数
2017/01/11 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
2017/06/14 Javascript
jQuery查找和过滤_动力节点节点Java学院整理
2017/07/04 jQuery
swiper 自动图片无限轮播实现代码
2018/05/21 Javascript
NodeJs之word文件生成与解析的实现代码
2019/04/01 NodeJs
vue+elementUI实现图片上传功能
2019/08/20 Javascript
Vue列表如何实现滚动到指定位置样式改变效果
2020/05/09 Javascript
[03:36]2014DOTA2 TI小组赛综述 八强诞生进军钥匙球馆
2014/07/15 DOTA
关于Python如何避免循环导入问题详解
2017/09/14 Python
Python SQLite3简介
2018/02/22 Python
python leetcode 字符串相乘实例详解
2018/09/03 Python
pycharm 批量修改变量名称的方法
2019/08/01 Python
Django文件上传与下载(FileFlid)
2019/10/06 Python
python基于gevent实现并发下载器代码实例
2019/11/01 Python
基于pytorch的lstm参数使用详解
2020/01/14 Python
基于keras输出中间层结果的2种实现方式
2020/01/24 Python
文史专业毕业生自荐信
2013/11/17 职场文书
大学生最常用的自我评价
2013/12/07 职场文书
法律专业实习鉴定
2013/12/22 职场文书
出纳会计岗位职责
2014/03/12 职场文书
护士长竞聘演讲稿
2014/04/30 职场文书
119消防日活动总结
2014/08/29 职场文书
redis 存储对象的方法对比分析
2021/08/02 Redis
解决Redis启动警告问题
2022/02/24 Redis