python利用requests库模拟post请求时json的使用教程


Posted in Python onDecember 07, 2018

我们都见识过requests库在静态网页的爬取上展现的威力,我们日常见得最多的为get和post请求,他们最大的区别在于安全性上:

1、GET是通过URL方式请求,可以直接看到,明文传输。

2、POST是通过请求header请求,可以开发者工具或者抓包可以看到,同样也是明文的。 3.GET请求会保存在浏览器历史纪录中,还可能会保存在Web的日志中。

两者用法上也有显著差异(援引自知乎):

1、GET用于从服务器端获取数据,包括静态资源(HTML|JS|CSS|Image等等)、动态数据展示(列表数据、详情数据等等)。

2、POST用于向服务器提交数据,比如增删改数据,提交一个表单新建一个用户、或修改一个用户等。

对于Post请求,我们可以通过浏览器开发者工具或者其他外部工具来进行抓包,得到请求的URL、请求头(request headers)以及请求的表单data信息,这三样恰恰是我们用requests模拟post请求时需要的,典型的写法如下:

response=requests.post(url=url,headers=headers,data=data_search)

由于post请求很多时候是配合Ajax(异步加载)技术一起使用的,我们抓包时,可以直接选择XHR(XmlHttpRequest)-ajax的一种对象,帮助我们滤掉其他的一些html、css、js类文件,如下图所示(截取自Chrome):

python利用requests库模拟post请求时json的使用教程

双击点开,就可以在页面右边的Headers页下看到General、Response Headers、Request Headers、Form Data几个模块,

其中General模块能看到请求的方法和请求的URL以及服务器返回的状态码(200(成功) 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。)

python利用requests库模拟post请求时json的使用教程

而Response Headers部分,可以看到缓存控制、服务器类型、返回内容格式、有效期等参数(笔者截图所示,返回的为json文件):

python利用requests库模拟post请求时json的使用教程

Request Header模块是非常重要的,可以有效地将我们的爬取行为模拟成浏览器行为,应对常规的服务器反爬机制:

其中Content-Type、Cookie以及User-Agent字段较为重要,需要我们构造出来(其他字段大多数时候,不是必须)

python利用requests库模拟post请求时json的使用教程

由于Cookie字段记录了用户的登陆信息,每次都不同,且同一个cookie存在一定有效期,当我们结合Selenium来组合爬取页面信息时,可以通过selenium完成网页的登陆校验,然后利用selenium提取出cookie,再转换为浏览器能识别的cookie格式,通常代码如下所示:

cookies = driver.get_cookies() #利用selenium原生方法得到cookies
ret=''
for cookie in cookies:
  cookie_name=cookie['name']
  cookie_value=cookie['value']
  ret=ret+cookie_name+'='+cookie_value+';' #ret即为最终的cookie,各cookie以“;”相隔开

紧接着,我们需要构造headers部分(即请求头),我们挑重点的几个字段进行构造:

headers={
  'Host':'**********.com',
  'Referer':'http://****************/check/index.do',
  'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
  'X-Requested-With':'XMLHttpRequest',
  'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
  'Cookie':ret #需要登陆后捕获cookie并调用
}

我们在网页中点击“确定”按钮,网页则会异步加载,后台发出post请求,取到json文件并渲染到网页表单中,比如我们根据需求填写了部分字段(这些就是我们post请求的data信息),然后观察后台的form data信息:

python利用requests库模拟post请求时json的使用教程

后台Form data 捕获到的data参数如图:

python利用requests库模拟post请求时json的使用教程

类似于字典格式,其中condition键对应的value较为复杂——列表中包含字典,字典中还有部分函数,其中字符串中既有单引号又有双引号交错。属于关键信息,page决定了网页的翻页在第几页,而rows则表示每次请求的数据限定的最大行数。

本例中问题的关键是,如何把想要的信息(譬如来源于excel配置文件)传递到condition字段对应的值内,确保Form data信息灵活可配置,大抵用法如下:

data_search={
  'page':1,
  'rows':15,
  'condition':
  """[\
    {"column":"BPM_DEF_NAME","exp":"like","value":""},\
    {"column":"DELETE_STATUS","exp":"=","value":0},\
    {"column":"TO_CHAR(TO_DATE(CREATE_DATE,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD')","exp":">=","value":"YYYY-MM-DD"},\
    {"column":"TO_CHAR(TO_DATE(CREATE_DATE,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD')","exp":"<=","value":"YYYY-MM-DD"},\
    {"column":"CHECK_TYPE","exp":"like","value":"2"},\
    {"column":"LOCKED_STATUS","exp":"=","value":0},\
    {"column":"DELETE_STATUS","orderType":"default","orderKey":"","direction":"ASC"}\
  ]""",  #考虑到该字段已经有单引号、双引号,所以只能用三引号来包住这部分代表字符串
  'additionalParams':'{}'
}
data_search_condition=json.loads(data_search['condition'])  #将字符串转为列表,方便更新列表(列表中每个元素都是一个单个字典)元素
#刷新字典
data_search_condition[0]['value']=businessName
data_search_condition[2]['value']=str(startDate)
data_search_condition[3]['value']=str(endDate)
data_search['condition']=json.dumps(data_search_condition) #将列表重新转回字符串,作为data_search字典中键“condition”对应的“value”,然后更新字典

上述代码中,data_search其实为字典对象,其键“condition”对应的值(三引号包住部分)为字符串,本质是json格式,我们如何对这部分动态传参呢?

这里需要用到python json包中常用的loads和dumps方法:

1、json.loads()是将json格式对象,转化Python可识别的字典对象。解码python json格式,可以用这个模块的json.loads()函数的解析方法。

2、json.dumps()是将一个Python数据类型列表进行json格式的编码解析,可以将一个list列表对象,进行了json格式的编码转换。

3、json.dump和json.dumps很不同,json.dump主要用来json文件读写,和json.load函数配合使用。

上面实例中,就是将data_search['condition'](json,字符串)转换为列表,然后根据列表定位到底层的每个dict字典,最后根据dict[Key]=value的方法进行更新(传参),更新完之后的列表,再通过json.dumps反向转回字符串,这样整个data_search字典中参数就可以灵活配置,通过外部引入了。

剩下的工作就很简单,交给强大的Requests包完成就好,示例代码如下:

def get_page(data_search,url): #定义页面解析的函数,返回值为json格式
  try:
    response=requests.post(url=url,headers=headers,data=data_search)
    if response.status_code==200:
      return response.json()
  except requests.ConnectionError as e:
    print('Error',e.args)

我们还可以把json格式内容存到本地(data.json)格式文件或者txt文本,并按照特定缩进(indent=4)进行规则排版,格式化内容,此时要用到json.dump()方法,示例代码如下:

for pageNum in range(1,1000):
  data_search['page']=str(pageNum)
  pageContent=get_page(data_search=data_search,url=url)
  with open('data.json','w',encoding="utf-8") as json_file:
    json.dump(pageContent,json_file,ensure_ascii = False,indent=4)
  if pageContent==None:
    print("无符合条件的单据!") 
    time.sleep(3)
    sys.exit(0)

格式化后的json看上去直观不少:

python利用requests库模拟post请求时json的使用教程

 

最后感慨一句:爬虫是门技术活,任何一个技术理解地不够透彻,碰到复杂的问题,可能就要花上很长时间去试错,譬如本文示例中的字典、json包几个功能的使用,稍微出错,就无法请求到对的数据!

PS:特别强调一点,有的时候requests.post()方法中data字段不填或者填写有误,服务器有时也会返回200状态码以及相应内容。这种情况下,我们一定要与手工操作得到的json文件进行对比,看看我们的传参(多测试几组不同的参数,看返回json内容是否不同)是否真的起到作用,以免空欢喜一场!

总结

以上所述是小编给大家介绍的python利用requests库模拟post请求时json的使用教程 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
简单文件操作python 修改文件指定行的方法
May 15 Python
解决python3中解压zip文件是文件名乱码的问题
Mar 22 Python
PyQt5每天必学之切换按钮
Aug 20 Python
Python延时操作实现方法示例
Aug 14 Python
对Python3中bytes和HexStr之间的转换详解
Dec 04 Python
Python小游戏之300行代码实现俄罗斯方块
Jan 04 Python
Python使用sqlalchemy模块连接数据库操作示例
Mar 13 Python
关于pytorch中网络loss传播和参数更新的理解
Aug 20 Python
Python动态导入模块和反射机制详解
Feb 18 Python
如何实现在jupyter notebook中播放视频(不停地展示图片)
Apr 23 Python
使用sklearn对多分类的每个类别进行指标评价操作
Jun 11 Python
python 用struct模块解决黏包问题
Nov 07 Python
Python 加密与解密小结
Dec 06 #Python
Python 带有参数的装饰器实例代码详解
Dec 06 #Python
DES加密解密算法之python实现版(图文并茂)
Dec 06 #Python
python获取时间及时间格式转换问题实例代码详解
Dec 06 #Python
python中ImageTk.PhotoImage()不显示图片却不报错问题解决
Dec 06 #Python
Python3非对称加密算法RSA实例详解
Dec 06 #Python
Python3对称加密算法AES、DES3实例详解
Dec 06 #Python
You might like
phpMyAdmin 安装配置方法和问题解决
2009/06/08 PHP
php设计模式之观察者模式的应用详解
2013/05/21 PHP
codeigniter框架The URI you submitted has disallowed characters错误解决方法
2014/05/06 PHP
php中in_array函数用法探究
2014/11/25 PHP
PHP实现自动对图片进行滚动显示的方法
2015/03/12 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
thinkphp框架page类与bootstrap分页(美化)
2017/06/25 PHP
删除重复数据的算法
2006/11/23 Javascript
css值转换成数值请抛弃parseInt
2011/10/24 Javascript
Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
2013/10/11 Javascript
jQuery中$.fn的用法示例介绍
2013/11/05 Javascript
用jquery中插件dialog实现弹框效果实例代码
2013/11/15 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
jQuery使用正则表达式限制文本框只能输入数字
2016/06/18 Javascript
微信小程序图片自适应支持多图实例详解
2017/06/21 Javascript
Nodejs模块的调用操作实例分析
2018/12/25 NodeJs
如何从头实现一个node.js的koa框架
2019/06/17 Javascript
浅析Vue中拆分视图层代码的5点建议
2019/08/15 Javascript
js删除指定位置超链接中含有百度与360的标题
2021/01/06 Javascript
node中短信api实现验证码登录的示例代码
2021/01/20 Javascript
使用python的chardet库获得文件编码并修改编码
2014/01/22 Python
Python获取任意xml节点值的方法
2015/05/05 Python
python解决字符串倒序输出的问题
2018/06/25 Python
Python unittest 简单实现参数化的方法
2018/11/30 Python
python通过移动端访问查看电脑界面
2020/01/06 Python
如何在Oracle中查看各个表、表空间占用空间的大小
2015/10/31 面试题
MYSQL支持事务吗
2013/08/09 面试题
临床医学应届生求职信
2013/11/06 职场文书
机电一体化专业推荐信
2013/12/03 职场文书
网管求职信
2014/03/03 职场文书
战略合作意向书
2014/07/29 职场文书
国际会计专业求职信
2014/08/04 职场文书
户籍证明书标准模板
2014/09/10 职场文书
2015年党务工作者个人工作总结
2015/10/22 职场文书
PHP策略模式写法
2021/04/01 PHP
pytorch 如何使用batch训练lstm网络
2021/05/28 Python