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 相关文章推荐
python去掉行尾的换行符方法
Jan 04 Python
Python拼接微信好友头像大图的实现方法
Aug 01 Python
对python Tkinter Text的用法详解
Oct 11 Python
python3 自动识别usb连接状态,即对usb重连的判断方法
Jul 03 Python
Python识别快递条形码及Tesseract-OCR使用详解
Jul 15 Python
Python实现的企业粉丝抽奖功能示例
Jul 26 Python
在PyCharm的 Terminal(终端)切换Python版本的方法
Aug 02 Python
python实现对图片进行旋转,放缩,裁剪的功能
Aug 07 Python
从训练好的tensorflow模型中打印训练变量实例
Jan 20 Python
Python Numpy 控制台完全输出ndarray的实现
Feb 19 Python
python模拟斗地主发牌
Apr 22 Python
python爬虫利用代理池更换IP的方法步骤
Feb 21 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笔记之:AOP的应用
2013/04/24 PHP
php通过数组实现多条件查询实现方法(字符串分割)
2014/05/06 PHP
PHP 面向对象程序设计之类属性与类常量实现方法分析
2020/04/13 PHP
基于jQuery图片平滑连续滚动插件
2009/04/27 Javascript
用户注册常用javascript代码
2009/08/29 Javascript
flexigrid 参数说明
2010/11/23 Javascript
javascript重写alert方法的实例代码
2013/03/29 Javascript
url参数中有+、空格、=、%、&、#等特殊符号的问题解决
2013/05/15 Javascript
jQuery自定义添加"$"与解决"$"冲突的方法
2015/01/19 Javascript
AngularJS 中文API参考手册
2016/07/28 Javascript
AngularJS 模块化详解及实例代码
2016/09/14 Javascript
简单几步实现返回顶部效果
2016/12/05 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
详解Vuex中mapState的具体用法
2017/09/28 Javascript
vue iview实现动态路由和权限验证功能
2018/04/17 Javascript
Vue 中如何正确引入第三方模块的方法步骤
2019/05/05 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
微信小程序自定义组件components(代码详解)
2019/10/21 Javascript
javascript开发实现贪吃蛇游戏
2020/07/31 Javascript
python使用PyV8执行javascript代码示例分享
2013/12/04 Python
python开发之IDEL(Python GUI)的使用方法图文详解
2015/11/12 Python
详解Python中的文件操作
2016/08/28 Python
Python脚本实现12306火车票查询系统
2016/09/30 Python
Python实现Linux监控的方法
2019/05/16 Python
python实现最大子序和(分治+动态规划)
2019/07/05 Python
Python中包的用法及安装
2020/02/11 Python
Python多线程Threading、子线程与守护线程实例详解
2020/03/24 Python
pandas数据拼接的实现示例
2020/04/16 Python
美国轮胎网站:Priority Tire
2018/11/28 全球购物
工程现场管理求职自荐信
2013/10/02 职场文书
四年级下册教学反思
2014/02/01 职场文书
《小猪家的桃花树》教学反思
2014/04/11 职场文书
《灰椋鸟》教学反思
2014/04/27 职场文书
pytorch显存一直变大的解决方案
2021/04/08 Python
python实现自动化群控的步骤
2021/04/11 Python
MySQL索引是啥?不懂就问
2021/07/21 MySQL