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之for循环语句
Oct 02 Python
Python2.7编程中SQLite3基本操作方法示例
Aug 09 Python
matplotlib在python上绘制3D散点图实例详解
Dec 09 Python
python使用筛选法计算小于给定数字的所有素数
Mar 19 Python
Python OS模块实例详解
Apr 15 Python
python 基于dlib库的人脸检测的实现
Nov 08 Python
为什么黑客都用python(123个黑客必备的Python工具)
Jan 31 Python
解决Tensorflow 内存泄露问题
Feb 05 Python
动态设置django的model field的默认值操作步骤
Mar 30 Python
Python ORM框架Peewee用法详解
Apr 29 Python
基于Python实现视频的人脸融合功能
Jun 12 Python
python调用摄像头的示例代码
Sep 28 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配置文件中最常用四个ini函数
2007/03/19 PHP
php FLEA中二叉树数组的遍历输出
2012/09/26 PHP
ThinkPHP在新浪SAE平台的部署实例
2014/10/31 PHP
php使用正则验证中文
2016/04/06 PHP
一种JavaScript的设计模式
2006/11/22 Javascript
javascript 类方法定义还是有点区别
2009/04/15 Javascript
JavaScript 解析读取XML文档 实例代码
2009/07/07 Javascript
javascript中[]和{}对象使用介绍
2013/03/20 Javascript
js获取本机的外网/广域网ip地址完整源码
2013/08/12 Javascript
JS排序方法(sort,bubble,select,insert)代码汇总
2016/01/30 Javascript
JS平滑无缝滚动效果的实现代码
2016/05/06 Javascript
全面了解构造函数继承关键apply call
2016/07/26 Javascript
对js eval()函数的一些见解
2016/08/15 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
jQuery基于Ajax方式提交表单功能示例
2017/02/10 Javascript
Flask中获取小程序Request数据的两种方法
2017/05/12 Javascript
基于Vue2.X的路由和钩子函数详解
2018/02/09 Javascript
微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)
2019/07/25 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
js实现简易计算器功能
2019/10/18 Javascript
jQuery HTML设置内容和属性操作实例分析
2020/05/20 jQuery
Python爬虫框架Scrapy安装使用步骤
2014/04/01 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
Pandas 数据处理,数据清洗详解
2018/07/10 Python
keras 自定义loss损失函数,sample在loss上的加权和metric详解
2020/05/23 Python
Python爬虫之Selenium设置元素等待的方法
2020/12/04 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
html5实现微信打飞机游戏
2014/03/27 HTML / CSS
《世界多美呀》教学反思
2014/03/02 职场文书
创先争优承诺书范文
2014/03/31 职场文书
保险内勤岗位职责
2015/04/13 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书
SQL SERVER实现连接与合并查询
2022/02/24 SQL Server
浅谈Vue的computed计算属性
2022/03/21 Vue.js
mysql 获取相邻数据项
2022/05/11 MySQL
Windows Server 2016服务器用户管理及远程授权图文教程
2022/08/14 Servers