更换Starlink ISP后Python Requests.get()请求异常如何解决?
解决Starlink网络下requests.get请求无响应问题
以下是针对Starlink网络环境中Python requests库请求无响应的几种无代理解决方案,按优先级尝试:
1. 强制使用IPv4连接
Starlink的IPv6路由可能存在异常,而requests默认优先尝试IPv6连接。可以通过两种方式强制使用IPv4:
方法A:手动解析IPv4并请求
import requests import socket main_url = "https://api.frankfurter.app/2023-10-22?from=EUR&to=USD" hostname = "api.frankfurter.app" # 获取域名的IPv4地址 ipv4 = socket.gethostbyname(hostname) # 构造请求时指定Host头,避免证书验证失败 response = requests.get( f"https://{ipv4}/2023-10-22?from=EUR&to=USD", headers={"Host": hostname}, verify=False # 若担心安全,可手动指定目标域名的证书路径 ) result = response.json() print(result)
方法B:全局强制requests使用IPv4
import requests import socket from urllib3.connection import HTTPConnection # 修改socket配置,强制使用IPv4 HTTPConnection.default_socket_options = ( HTTPConnection.default_socket_options + [(socket.IPPROTO_IP, socket.IPV6_V6ONLY, 0)] ) main_url = "https://api.frankfurter.app/2023-10-22?from=EUR&to=USD" response = requests.get(main_url, timeout=10) result = response.json() print(result)
2. 切换到支持HTTP/2的客户端
浏览器默认使用HTTP/2协议,而requests库默认仅支持HTTP/1.1。Starlink卫星网络对HTTP/2的多路复用兼容性更好,可改用httpx库:
import httpx main_url = "https://api.frankfurter.app/2023-10-22?from=EUR&to=USD" # 启用HTTP/2支持 with httpx.Client(http2=True) as client: response = client.get(main_url, timeout=10) result = response.json() print(result)
3. 调整TCP连接存活参数
卫星网络延迟较高,TCP连接容易被判定为闲置而断开。通过自定义requests适配器开启TCP keepalive:
import requests import socket from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class KeepAliveAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 设置TCP keepalive参数 kwargs['socket_options'] = [ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60), # 60秒后开始发送心跳 (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10), # 心跳间隔10秒 (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3) # 失败3次后断开 ] return super().init_poolmanager(*args, **kwargs) # 创建会话并挂载适配器 session = requests.Session() session.mount('https://', KeepAliveAdapter()) main_url = "https://api.frankfurter.app/2023-10-22?from=EUR&to=USD" response = session.get(main_url, timeout=10) result = response.json() print(result)
4. 更换DNS解析服务器
Starlink内置DNS可能存在解析延迟或错误,手动指定公共DNS(如Google 8.8.8.8)解析域名:
import requests import dns.resolver # 指定公共DNS服务器 resolver = dns.resolver.Resolver() resolver.nameservers = ['8.8.8.8'] # 解析域名的IPv4地址 answer = resolver.resolve('api.frankfurter.app', 'A') ipv4 = answer[0].address # 用解析后的IPv4发起请求 response = requests.get( f"https://{ipv4}/2023-10-22?from=EUR&to=USD", headers={"Host": "api.frankfurter.app"}, verify=False ) result = response.json() print(result)
内容的提问来源于stack exchange,提问作者Matthieu Morel
相关产品推荐
相关产品推荐

