You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

urllib批量请求代理异常:单请求正常批量返回404求助

解决Squid代理下urllib批量请求返回404的问题

我来帮你揪出这个问题的根源!

你遇到的核心问题是:处理HTTPS URL时,代理协议设置错误。

看你的代码,不管目标URL是HTTP还是HTTPS,你都固定用req.set_proxy(proxy_host, 'http')来设置代理。但urllib的set_proxy方法第二个参数是用来指定该代理对应哪种请求协议的——如果你的请求目标是HTTPS地址,这个参数必须设为'https',否则urllib不会正确通过Squid代理去请求HTTPS资源,导致请求直接走本地网络(而你的环境强制要求走代理,所以返回404)。

单请求时可能Squid做了兼容处理,侥幸成功了,但批量或多进程请求时,这种协议不匹配的问题就彻底暴露出来了。

给你两个靠谱的修复方案:

方案一:根据URL协议动态匹配代理协议

修改check_url函数,先解析URL的协议部分,再对应设置代理协议:

from multiprocessing import Pool
import urllib.error
import urllib.request
from urllib.parse import urlparse

proxy_host = "192.168.1.1:3128"
urls = ['https://www.youtube.com/watch?v=XqZsoesa55w', 'https://www.youtube.com/watch?v=GR2o6k8aPlI', 'https://stackoverflow.com/']

def check_url(url):
    # 解析出URL的协议(http/https)
    parsed_url = urlparse(url)
    req = urllib.request.Request(
        url=url,
        data=None,
        headers={'User-Agent': 'Mozilla/5.0'}
    )
    # 按URL协议设置对应的代理协议
    req.set_proxy(proxy_host, parsed_url.scheme)
    try:
        with urllib.request.urlopen(req) as conn:
            return conn.getcode()
    except urllib.error.HTTPError as e:
        return [str(e), url]
    except urllib.error.URLError as e:
        return [str(e), url]
    except ValueError as e:
        return [str(e), url]
    else:
        return 'Unknown Status!'

# 测试循环调用
for url in urls:
    print(check_url(url))

# 测试多进程调用
p = Pool(processes=20)
print(p.map(check_url, urls))

方案二:全局代理处理器(更简洁省心)

直接创建全局的代理处理器,让所有请求自动走代理,不用每个Request单独设置,从根源避免协议匹配错误:

from multiprocessing import Pool
import urllib.error
import urllib.request

proxy_host = "192.168.1.1:3128"
urls = ['https://www.youtube.com/watch?v=XqZsoesa55w', 'https://www.youtube.com/watch?v=GR2o6k8aPlI', 'https://stackoverflow.com/']

# 构建代理处理器,同时处理http和https请求
proxy_handler = urllib.request.ProxyHandler({
    'http': f'http://{proxy_host}',
    'https': f'http://{proxy_host}'
})
# 创建全局opener并安装
opener = urllib.request.build_opener(proxy_handler)
urllib.request.install_opener(opener)

def check_url(url):
    req = urllib.request.Request(
        url=url,
        data=None,
        headers={'User-Agent': 'Mozilla/5.0'}
    )
    try:
        with urllib.request.urlopen(req) as conn:
            return conn.getcode()
    except urllib.error.HTTPError as e:
        return [str(e), url]
    except urllib.error.URLError as e:
        return [str(e), url]
    except ValueError as e:
        return [str(e), url]
    else:
        return 'Unknown Status!'

# 测试循环调用
for url in urls:
    print(check_url(url))

# 测试多进程调用
p = Pool(processes=20)
print(p.map(check_url, urls))

这个方案更稳妥,因为它统一处理了HTTP和HTTPS请求的代理配置,而且多进程环境下,每个子进程都会继承全局opener的设置,不会出现冲突问题。

内容的提问来源于stack exchange,提问作者F. JAF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:34:29