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的Supervisor进行进程监控以及自动启动
May 29 Python
Python的另外几种语言实现
Jan 29 Python
Python计算回文数的方法
Mar 11 Python
python获取当前计算机cpu数量的方法
Apr 18 Python
django使用html模板减少代码代码解析
Dec 12 Python
教你使用python实现微信每天给女朋友说晚安
Mar 23 Python
利用Python如何实现数据驱动的接口自动化测试
May 11 Python
对Python 3.2 迭代器的next函数实例讲解
Oct 18 Python
对python修改xml文件的节点值方法详解
Dec 24 Python
python字典排序的方法
Oct 12 Python
Python操作Excel把数据分给sheet
May 20 Python
Python办公自动化PPT批量转换操作
Sep 15 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
JS 网站性能优化笔记
2011/05/24 PHP
浅谈PHP的反射机制
2016/12/15 PHP
PHP使用Session实现上传进度功能详解
2019/08/06 PHP
javaScript 动态访问JSon元素示例代码
2013/08/30 Javascript
轻量级网页遮罩层jQuery插件用法实例
2015/07/31 Javascript
javascript字符串函数汇总
2015/12/06 Javascript
jquery中ajax跨域方法实例分析
2015/12/18 Javascript
打造自己的jQuery插件入门教程
2016/09/23 Javascript
ReactJs快速入门教程(精华版)
2016/11/28 Javascript
nodeJS实现路由功能实例代码
2017/06/08 NodeJs
iscroll.js滚动加载实例详解
2017/07/18 Javascript
你应该知道的几类npm依赖包管理详解
2017/10/06 Javascript
form表单数据封装成json格式并提交给服务器的实现方法
2017/12/14 Javascript
AngularJs1.x自定义指令独立作用域的函数传入参数方法
2018/10/09 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
python如何通过protobuf实现rpc
2016/03/06 Python
Python正则表达式常用函数总结
2017/06/24 Python
Python使用pickle模块实现序列化功能示例
2018/07/13 Python
python模拟登陆,用session维持回话的实例
2018/12/27 Python
PyQt5事件处理之定时在控件上显示信息的代码
2020/03/25 Python
GUESS盖尔斯法国官网:美国时尚品牌
2016/09/23 全球购物
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
几道数据库的概念性面试题
2014/05/30 面试题
什么是触发器(trigger)? 触发器有什么作用?
2013/09/18 面试题
机电一体化职业规划书
2014/01/07 职场文书
给面试官的感谢信
2014/02/01 职场文书
大型活动组织方案
2014/05/10 职场文书
服务承诺书范文
2014/05/19 职场文书
小学生五年级大队长竞选发言稿
2014/09/12 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
群众路线教育实践活动实施方案
2014/10/31 职场文书
2014年技术工作总结范文
2014/11/20 职场文书
2014年销售人员工作总结
2014/11/27 职场文书
我是特种兵观后感
2015/06/11 职场文书
详解Spring事件发布与监听机制
2021/06/30 Java/Android
Java移除无效括号的方法实现
2021/08/07 Java/Android