使用urllib调用OpenWeatherMap遇403 URLBlocked错误求助
解决方案:urllib请求OpenWeatherMap遇403 URLBlocked错误(curl可正常请求)
问题背景
使用Python urllib库请求OpenWeatherMap API时触发以下错误:
urllib.error.URLError: <urlopen error Tunnel connection failed: 403 URLBlocked>
已确认请求URL正确,且同一服务器上执行curl命令可成功获取数据:
curl -k --location --request GET 'https://xxxxxxxxxxxxx/owm/v1/data/2.5/onecall/timemachine?lat=51.2&lon=6.4&dt=1667390504&appid=xxxxxxxxxxxxx&units=metric' --header 'client_id: xxxxxxxxxxxxx' --header 'client_secret: xxxxxxxxxxxxx'
核心差异分析
你的curl命令包含两个urllib代码未处理的关键逻辑,同时请求头和代理设置也存在不一致:
-k:忽略SSL证书验证--location:自动跟随HTTP重定向- curl默认的User-Agent与urllib设置的
Mozilla/6.0不同,可能触发反爬拦截 - curl未使用代理,但urllib代码中强制设置了代理
具体修复步骤
1. 对齐SSL证书验证逻辑
curl用-k跳过了证书验证,若你的self.gcontext未正确配置该逻辑,可重新创建不验证证书的上下文:
import ssl import urllib.request # 创建不验证SSL证书的上下文 context = ssl._create_unverified_context()
2. 启用自动重定向
urllib的Request默认不跟随3xx重定向,需显式开启:
api_key = self.dict_config["api_key"] urlweather = self.dict_config["weather_url"] % (lat, lon, dt, api_key) request = urllib.request.Request(urlweather, method='GET') # 复制curl的请求头,包括client_id、client_secret request.add_header('client_id','xxxxxxxxxxxxx') request.add_header('client_secret','xxxxxxxxxxxxx') # 改用curl默认的User-Agent,避免被反爬拦截(可通过curl -v查看实际版本) request.add_header('User-Agent', 'curl/7.68.0') # 注释代理设置,和curl保持一致(若必须用代理,需检查代理白名单/认证) # proxy='xxxxxxxxxxxxx:8080' # request.set_proxy(proxy, 'https') # 启用重定向并使用新的上下文 with urllib.request.urlopen(request, context=context, redirect=True) as response: weather = response.read().decode() return weather
3. 排查代理(若必须使用)
如果业务需要代理,需确认:
- 代理服务器是否允许访问目标OpenWeatherMap域名
- 是否需要添加代理认证头(如
Proxy-Authorization: Basic base64(用户名:密码))
4. 完全对齐请求头
可通过curl -v命令查看完整请求头,将所有头信息复制到urllib中,确保和curl请求完全一致:
curl -v -k --location --request GET '你的请求URL' --header 'client_id: xxx' --header 'client_secret: xxx'
内容的提问来源于stack exchange,提问作者FrozzenFinger
相关产品推荐
相关产品推荐

