前排提醒!

本文并非是“零起点”的。阅读下列文档之前,请保证你具有以下的知识:

了解requests和grequests模块,并能够使用其建立HTTP请求;

了解回调函数的含义。

背景

进行爬虫操作时,程序员除了想要获取请求的结果之外,有时还想在请求过程中获取相关的信息(比如说在某个时刻已请求数据的长度),以完成某些任务(比如说下载进度条)。我们知道Python内置模块urllib下的方法urllib.request.urlretrieve可以添加回调函数参数callback,但是在另外一个常用模块requests中,我们难以找到直接的回调函数参数,在国内互联网中也难以找到相关信息,但这不代表这个模块完不成这个任务。在此我查阅了一些资料和问答频道,并写成此文,以供参考。

研究

以下我们以添加GET请求的进度条的方式来展示改进方法。

requests没有直接的callback参数(这一点待定),但是其具有一个参数“流”(stream)允许我们以流的形式进行请求。以流形式请求时,我们可以“一块”(chunk)“一块”地获取请求的内容,请求对象Response在此时不会再全部内容完全被获取时才能返回;并且Response支持生成器iter_content的方式来返回请求的内容。由以上二点,我们可以构造一个新的请求函数,来做出回调函数的效果:

注:本方法源自Stack Overflow某条回答,源地址遗失。

def get_callback(url, data=None, chunk_size=1024, callback=None):

r = requests.get(url, data=data, stream=True) # Response请求,由于添加了stream,请求速度不会慢

length = r.headers.get('content-length') # 请求的总长度,便于回调

if length == None: # 有的请求不带上面的头参数,故要特判

return r.content # 直接返回

if not callback: # 如果回调函数没有给定

callback = lambda now, tot: None # 一个无用的函数,占位用,其中callback需要接受两个参数,分别对应已获取长度和总长度,后同

dl = 0 # 目前已获取的长度

length = int(length) # headers里取得的值都是字符串,要化成整数

res = b'' # 目前已获取的请求内容

for chunk in r.iter_content(chunk_size=chunk_size): # 每次取出一块,注意chunk_size在requests中默认为1,这里调大为1024,节约for循环的成本

dl += len(chunk)

res = b''.join([res, chunk]) # 这里没有直接加,速度更快

callback(dl, length) # 执行回调

return res # 最终给出请求的内容

测试结果如下:

In [63]: res = get_callback(url, None, 1048576, callback)

1048576 35984960

2097152 35984960

3145728 35984960

4194304 35984960

5242880 35984960

6291456 35984960

7340032 35984960

8388608 35984960

9437184 35984960

10485760 35984960

11534336 35984960

12582912 35984960

13631488 35984960

14680064 35984960

15728640 35984960

16777216 35984960

17825792 35984960

18874368 35984960

19922944 35984960

20971520 35984960

22020096 35984960

23068672 35984960

24117248 35984960

25165824 35984960

26214400 35984960

27262976 35984960

28311552 35984960

29360128 35984960

30408704 35984960

31457280 35984960

32505856 35984960

33554432 35984960

34603008 35984960

35651584 35984960

35984960 35984960

In [64]: len(res)

Out[64]: 35984960

如果我们需要时刻对某个变量赋值,而不是print,我们可以在callback中添加global语句,使回调函数可以修改外部全局变量。

但如果是第三方进度条模块(比如说progressbar),则可能需要对源代码改进较多,原因是进度条的实现需要将iter_content视作某个函数的自变量,并且进度条模块通常对生成器不友好(原因是生成器迭代次数无法确定,也就无法判断最大循环次数。但是我们先前已经得到了chunk_size和length两个变量,而整个过程不包括其他的循环,故我们可以计算得出总共的循环次数:

max_value = int(math.ceil(length / chunk_size))

以此我们得出回调的改进版:

def get_callback(url, data=None, chunk_size=1024, callback=None):

r = requests.get(url, data=data, stream=True)

length = r.headers.get('content-length')

if length == None:

return r.content

if not callback:

callback = lambda now, tot: None

dl = 0

length = int(length)

res = b''

max_value = int(math.ceil(length / chunk_size))

bar = progressbar.ProgressBar(max_value=max_value) # 设定进度条的最大循环次数

for chunk in bar(r.iter_content(chunk_size=chunk_size)):

dl += len(chunk)

res = b''.join([res, chunk])

callback(dl, length)

return res

由于进度条并未占用callback参数,我们依然可以另添一个回调函数完成其他任务。

全文完。

pythonrequest函数_[Python]requests模块:HTTP请求时的回调函数相关推荐

  1. 记录python requests模块及请求重试

    记录python requests模块及请求重试 1.打开charles,手机连接charles代理,然后手机登陆微信(ylgy)小游戏,通过第一关,获取https://cat-match.easyg ...

  2. python requests cookiejar,Python requests模块cookie实例解析

    cookie并不陌生,与session一样,能够让http请求前后保持状态.与session不同之处,在于cookie数据仅保存于客户端.requests也提供了相应到方法去处理cookie. 在py ...

  3. Python urllib3和requests发送HTTPS请求时出现SSLError或InsecureRequestWarning

    目录 问题及原因分析 优先考虑的解决方法: 下载证书 使用证书 手动获取证书 不推荐使用的备用解决方法: 关闭方法 衍生问题 参考文档 问题及原因分析 在我们通过urllib3和requests进行H ...

  4. python requests下载图片_python读取图片大小Python Requests模块快速入门

    requests是python的一个HTTP客户端库,跟urllib,urllib2类似.它比 urllib 更加方便,可以节约我们大量的工作,它比 urllib 更加 Pythoner. 安装 Re ...

  5. mitmdump脚本中使用requests模块发送请求

    本文仅供学习交流使用,如侵立删! 环境 win10.Windows Server 2008 R2 python3.9 mitmdump4.0 mitmdump脚本中使用requests模块发送请求 m ...

  6. Python—requests模块详解

    Python-requests模块详解 来源(博客园@小L小 ):Python-requests模块详解

  7. 使用 python requests 模块发送 http 请求及接收响应

    内容概要 如何构建GET 与 POST request 请求消息 对 request 的header , query string, message body 定制化 http header参数 co ...

  8. Python requests模块高级用法

    2019独角兽企业重金招聘Python工程师标准>>> 快速入门的话可以参考这篇文章,但是进阶的话还是建议参考官方的文档,毕竟官方的文档更新比较及时,也有些高级用法,猛戳这里! 会话 ...

  9. python requests模块解析html_用python3教你任意Html主内容提取

    0x1 工具准备 工欲善其事必先利其器,爬取语料的根基便是基于python. 我们基于python3进行开发,主要使用以下几个模块:requests.lxml.json. 简单介绍一个各模块的功能 0 ...

最新文章

  1. ×××作,不知写些什么
  2. Colab不好用,有人花两年开发了一个新notebook,支持实时协作还更快
  3. 使用Javascript获取图片坐标以及宽度高度的方法
  4. 巴特沃斯滤波器应用场合_巴特沃斯数字低通滤波器设计及应用
  5. pyspider all 只启动了_我是如何让微博绿洲的启动速度提升30%的(二)
  6. 塔菲尔曲线斜率的大小_中国第一塔,与埃菲尔铁塔齐名,到底有多强悍?
  7. MXRuntimeUtils,替代 [NSObject performSelector object object ]的工具
  8. 华为路由器显示连接到服务器失败怎么办,华为路由器设置好了不能用怎么办 华为路由器无法上网问题-192路由网...
  9. jupyter notebook 更改工作环境和浏览器
  10. 转载HTML实体字符
  11. 新动态视频壁纸微信小程序源码_支持多种分类短视频-也有静态壁纸
  12. 最小二乘法--通俗解释
  13. realme 拨号代码_手机拨号界面为什么会有quot;*和#quot;键?这2个键有什么用?望周知...
  14. 用Java实现,把Byte,相应的转换为KB,MB,GB,TB
  15. python搜索文献 速成_0基础5天速成Python,你也能发top期刊
  16. 基于STM32视频监控系统
  17. Linux文件目录操作命令-more命令
  18. 验证码图片显示不出文字
  19. 碳足迹软件市场现状研究分析-
  20. 安卓开发文档!花三分钟看完这篇文章你就懂了!帮你突破瓶颈

热门文章

  1. JEECG - 基于代码生成器的J2EE智能开发框架 续五:权限设计
  2. 微服务技术栈:常见注册中心组件,对比分析
  3. JavaEE基础(06):Servlet整合C3P0数据库连接池
  4. Shell脚本语言常用命令总结~
  5. UI交互设计关键词:情感化设计与心理
  6. 关于centos 7 中service iptables save 指令使用失败的结局方案
  7. 传统反病毒软件厂商学会新把戏
  8. iptables控制较复杂案例
  9. datastage 作业查找脚本
  10. Codeforces Round #114 (Div. 2)