使用Python requests的get()方法如何处理无协议域名链接?
关于Requests请求域名的协议处理问题
首先明确一点:你不能直接用requests.get('facebook.com', headers=headers)这种方式发送请求。因为Requests库要求传入的URL必须包含完整的协议头(http://或https://),否则会抛出InvalidSchema异常——它根本不知道要通过哪种协议去和目标服务器建立连接。
你当前采用的「先试HTTPS,失败再降级到HTTP」的思路是可行的,但有几个可以优化的地方,下面展开说:
一、当前写法的不足与改进
你现在的代码用了裸except,这会捕获所有类型的异常(比如网络超时、服务器返回500错误等),可能导致你无法区分「确实是HTTPS不可用」还是「其他请求错误」。建议改成捕获特定的、和协议相关的异常:
import requests headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"} def fetch_url(url): # 先处理不带协议的URL if not url.startswith(('http://', 'https://')): # 优先尝试HTTPS try: resp = requests.get(f"https://{url}", headers=headers, timeout=10) resp.raise_for_status() # 主动触发非2xx状态码的异常 return resp # 捕获HTTPS相关的失败情况:证书错误、无法建立SSL连接、超时 except (requests.exceptions.SSLError, requests.exceptions.ConnectionError, requests.exceptions.Timeout): # 降级到HTTP尝试 try: resp = requests.get(f"http://{url}", headers=headers, timeout=10) resp.raise_for_status() return resp except Exception as e: print(f"请求 {url} 失败:{str(e)}") return None # 处理已经带协议的URL else: try: resp = requests.get(url, headers=headers, timeout=10) resp.raise_for_status() return resp except Exception as e: print(f"请求 {url} 失败:{str(e)}") return None
二、其他优化思路
- 用HEAD请求替代GET做前置检查:HEAD请求只返回响应头,比GET请求更轻量,可以先通过HEAD确认协议可用性,再发送GET请求获取内容,减少带宽消耗。
- 前置端口检查:可以先尝试连接目标域名的443端口(HTTPS默认端口),如果能连通再试HTTPS,否则直接用HTTP。不过这种方式不绝对,有些网站443端口开放但SSL配置有问题,还是会请求失败。
三、总结
- 必须给URL加上协议头,不能直接传纯域名;
- 「HTTPS优先,失败降级HTTP」是通用且有效的方案,但要注意捕获特定异常,避免隐藏其他问题;
- 根据场景可以用HEAD请求或端口检查来优化请求流程。
内容的提问来源于stack exchange,提问作者Slava Bugz
相关产品推荐
相关产品推荐

