详解Python requests 超时和重试的方法


Posted in Python onDecember 18, 2018

网络请求不可避免会遇上请求超时的情况,在 requests 中,如果不设置你的程序可能会永远失去响应。

超时又可分为连接超时和读取超时。

连接超时

连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是 connect() ),Request 等待的秒数。

import time
import requests

url = 'http://www.google.com.hk'

print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
  html = requests.get(url, timeout=5).text
  print('success')
except requests.exceptions.RequestException as e:
  print(e)

print(time.strftime('%Y-%m-%d %H:%M:%S'))

因为 google 被墙了,所以无法连接,错误信息显示 connect timeout(连接超时)。

2018-12-14 14:38:20
HTTPConnectionPool(host='www.google.com.hk', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000000047F80F0>, 'Connection to www.google.com.hk timed out. (connect timeout=5)'))
2018-12-14 14:38:25

就算不设置,也会有一个默认的连接超时时间(我测试了下,大概是21秒)。

读取超时

读取超时指的就是客户端等待服务器发送请求的时间。(特定地,它指的是客户端要等待服务器发送字节之间的时间。在 99.9% 的情况下这指的是服务器发送第一个字节之前的时间)。

简单的说,连接超时就是发起请求连接到连接建立之间的最大时长,读取超时就是连接成功开始到服务器返回响应之间等待的最大时长。

读取超时是没有默认值的,如果不设置,程序将一直处于等待状态。 我们的爬虫经常卡死又没有任何的报错信息,原因就在这里了。

如果你设置了一个单一的值作为 timeout,如下所示:

r = requests.get('https://github.com', timeout=5)

这一 timeout 值将会用作 connect 和 read 二者的 timeout。如果要分别制定,就传入一个元组:

r = requests.get('https://github.com', timeout=(3.05, 27))

黑板课爬虫闯关的第四关正好网站人为设置了一个15秒的响应等待时间,拿来做说明最好不过了。

import time
import requests

url_login = 'http://www.heibanke.com/accounts/login/?next=/lesson/crawler_ex03/'

session = requests.Session()
session.get(url_login)

token = session.cookies['csrftoken']
session.post(url_login, data={'csrfmiddlewaretoken': token, 'username': 'guliang21', 'password': '123qwe'})

print(time.strftime('%Y-%m-%d %H:%M:%S'))

url_pw = 'http://www.heibanke.com/lesson/crawler_ex03/pw_list/'
try:
  html = session.get(url_pw, timeout=(5, 10)).text
  print('success')
except requests.exceptions.RequestException as e:
  print(e)

print(time.strftime('%Y-%m-%d %H:%M:%S'))

错误信息中显示的是 read timeout(读取超时)。

2018-12-14 15:20:47
HTTPConnectionPool(host='www.heibanke.com', port=80): Read timed out. (read timeout=10)
2018-12-14 15:20:57

超时重试

一般超时我们不会立即返回,而会设置一个三次重连的机制。

def gethtml(url):
  i = 0
  while i < 3:
    try:
      html = requests.get(url, timeout=5).text
      return html
    except requests.exceptions.RequestException:
      i += 1

其实 requests 已经帮我们封装好了。(但是代码好像变多了…)

import time
import requests
from requests.adapters import HTTPAdapter

s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))

print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
  r = s.get('http://www.google.com.hk', timeout=5)
  return r.text
except requests.exceptions.RequestException as e:
  print(e)
print(time.strftime('%Y-%m-%d %H:%M:%S'))

max_retries 为最大重试次数,重试3次,加上最初的一次请求,一共是4次,所以上述代码运行耗时是20秒而不是15秒

2018-12-14 15:34:03
HTTPConnectionPool(host='www.google.com.hk', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x0000000013269630>, 'Connection to www.google.com.hk timed out. (connect timeout=5)'))
2018-12-14 15:34:23

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python的函数的一些高阶特性
Apr 27 Python
Python的爬虫包Beautiful Soup中用正则表达式来搜索
Jan 20 Python
python3+PyQt5使用数据库表视图
Apr 24 Python
Anaconda下安装mysql-python的包实例
Jun 11 Python
Python内置random模块生成随机数的方法
May 31 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
Jul 11 Python
PyQtGraph在pyqt中的应用及安装过程
Aug 04 Python
python正则表达式实例代码
Mar 03 Python
Python numpy矩阵处理运算工具用法汇总
Jul 13 Python
python 爬取免费简历模板网站的示例
Sep 27 Python
Django怎么在admin后台注册数据库表
Nov 14 Python
Python字符串常规操作小结
Apr 03 Python
解决新django中的path不能使用正则表达式的问题
Dec 18 #Python
python 获取url中的参数列表实例
Dec 18 #Python
python 函数内部修改外部变量的方法
Dec 18 #Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
Dec 18 #Python
python监测当前联网状态并连接的实例
Dec 18 #Python
Python实现繁体中文与简体中文相互转换的方法示例
Dec 18 #Python
解决python3 pika之连接断开的问题
Dec 18 #Python
You might like
PHP版国家代码、缩写查询函数代码
2011/08/14 PHP
PHP面向对象程序设计高级特性详解(接口,继承,抽象类,析构,克隆等)
2016/12/02 PHP
PHP数字前补0的自带函数sprintf 和number_format的用法(详解)
2017/02/06 PHP
Laravel5.5 手动分页和自定义分页样式的简单实现
2019/10/15 PHP
Centos7安装swoole扩展操作示例
2020/03/26 PHP
仅IE支持clearAttributes/mergeAttributes方法使用介绍
2012/05/04 Javascript
JQuery获取各种宽度、高度(format函数)实例
2013/03/04 Javascript
Javascript玩转继承(三)
2014/05/08 Javascript
js动态添加表格数据使用insertRow和insertCell实现
2014/05/22 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
angularjs 处理多个异步请求方法汇总
2015/01/06 Javascript
jquery中radio checked问题
2015/03/16 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
JS实现json的序列化和反序列化功能示例
2017/06/13 Javascript
通过jquery的ajax请求本地的json文件方法
2018/08/08 jQuery
详解实现一个通用的“划词高亮”在线笔记功能
2019/04/23 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
2019/09/17 Javascript
VUE实现自身整体组件销毁的示例代码
2020/01/13 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
[48:45]Ti4 循环赛第二日 NEWBEE vs EG
2014/07/11 DOTA
[03:15]2014DOTA2国际邀请赛 专访国士无双信心满满
2014/07/12 DOTA
详解pandas数据合并与重塑(pd.concat篇)
2019/07/09 Python
基于matplotlib中ion()和ioff()的使用详解
2020/06/16 Python
CSS3 毛玻璃效果
2019/08/14 HTML / CSS
招聘单位介绍信
2014/01/14 职场文书
安全大检查反思材料
2014/01/31 职场文书
《故都的秋》教学反思
2014/04/15 职场文书
产品推广策划方案
2014/05/10 职场文书
网吧消防安全责任书
2014/07/29 职场文书
师德师风个人总结
2015/02/06 职场文书
社区植树节活动总结
2015/02/06 职场文书
2015年依法行政工作总结
2015/04/29 职场文书
法定授权委托证明书
2015/06/18 职场文书
2016年3月份红领巾广播稿
2015/12/21 职场文书
详解RedisTemplate下Redis分布式锁引发的系列问题
2021/04/27 Redis
新手入门Jvm-- JVM对象创建与内存分配机制
2021/06/18 Java/Android