问题描述

用python requests,urllib访问网页速度非常慢,但是用postman等其他应用访问是正常的

问题重现

import requests
url = 'https://www.example.com'

%time requests.get(url)
 Wall time: 20 s

分析原因

默认requests会使用IPv6进行连接,如果IPv6超时再使用IPv4请求,可以给请求添加一个timeout=5来进行检查,其原理是设置很低的timeout迫使requests在更短的时间内切换到IPv4

%time requests.get(url, timeout=5)
 Wall time: 300 ms

如果成功返回,则说明问题出在IPv6上面,其中一种解决方法是禁用本机的IPv6

解决方案

方法1. 禁用Windows10的IPv6

  1. 右键单击右下角托盘区域的 网络 图标
  2. 单击 打开网路和Internet设置
  3. 单击 更改适配器选项
  4. 右键你当前使用的网卡名称,我这里是 以太网
  5. 单击 属性
  6. 取消选中 Internet 协议版本 6(TCP/IPv6)
  7. 单击 确定 保存更改

方法2. 强制requests使用IPv4

在文件开头引入下面内容

import socket
import urllib3.util.connection as urllib3_cn
    
   
def allowed_gai_family():
    """
     https://github.com/shazow/urllib3/blob/master/urllib3/util/connection.py
    """
    family = socket.AF_INET
    if urllib3_cn.HAS_IPV6:
        family = socket.AF_INET6 # 只有当连接的IPv6可用时才使用
    return family

urllib3_cn.allowed_gai_family = allowed_gai_family

或者强制所有连接使用IPv4

import urllib3.util.connection as urllib3_cn
urllib3_cn.HAS_IPV6 = False

参考链接

  1. https://stackoverflow.com/questions/62599036/python-requests-is-slow-and-takes-very-long-to-complete-http-or-https-request

  2. https://stackoverflow.com/questions/33046733/force-requests-to-use-ipv4-ipv6/46972341#46972341