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

使用Python进行Web Scraping:仅本地正常,其他环境均返回403错误

问题排查与解决方案

针对本地运行正常、Docker/其他机器执行返回403的问题,以下是具体排查方向和修复方案:

1. 补全请求头,避免指纹识别

目标网站可能会检测请求头的完整性,仅设置User-Agent不足以模拟正常浏览器请求。建议在代码中补充常见标准请求头:

def request_with_proxy(url, headers={}):
    # 补全通用请求头
    default_headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.5',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1'
    }
    default_headers.update(headers)
    # 添加随机User-Agent
    default_headers["User-Agent"] = user_agent_rotator.get_random_user_agent()
    
    # 代理配置(原代码保持不变)
    try:
        proxy_url = f'http://{os.environ["PROXY_USER"]}:{os.environ["PROXY_PASSWORD"]}@p.webshare.io:80'
        proxies = {
            'http': proxy_url,
            'https': proxy_url
        }
    except:
        raise TypeError("MISSING PROXY ENVIRONMENT VARIABLES PROXY_USER AND PROXY_PASSWORD")
    
    # 使用Session复用连接,减少异常指纹
    session = requests.Session()
    session.headers.update(default_headers)
    session.proxies.update(proxies)
    
    # 重试逻辑
    for _ in range(ATTEMPTS):
        try:
            response = session.get(url, timeout=TIMEOUT)
            print(response.status_code)
            return response
        except Exception as e: 
            print(e)
            session.close()

2. 统一TLS/SSL版本

Python Slim镜像默认的OpenSSL版本可能较旧,与目标网站的TLS兼容性存在差异。修改Dockerfile更新SSL组件:

FROM python:3.10.12-slim

# 设置时区(匹配目标网站所在地区,德国站用Europe/Berlin)
ENV TZ=Europe/Berlin
RUN apt-get update -y && \
    apt-get install -y postgresql postgresql-contrib openssl tzdata && \
    rm -rf /var/lib/apt/lists/* && \
    pip install --no-cache-dir -r requirements.txt && \
    rm -rf /root/.cache && \
    apt-get autoremove -y

ENV PYTHONUNBUFFERED=1

CMD ["python", "main.py"]

同时在请求中强制指定TLS1.2+版本:

import ssl
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager

class TLSAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        ctx = ssl.create_default_context()
        ctx.set_ciphers('DEFAULT@SECLEVEL=1')
        ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
        kwargs['ssl_context'] = ctx
        return super(TLSAdapter, self).init_poolmanager(*args, **kwargs)

# 在session中挂载适配器
session.mount('https://', TLSAdapter())

3. 验证User-Agent有效性

检查容器中生成的User-Agent是否与本地一致,部分旋转库在容器环境下可能生成异常UA(如过旧或非标准格式)。可以临时打印UA对比:

ua = user_agent_rotator.get_random_user_agent()
print(f"Using UA: {ua}")

若存在差异,建议更换更稳定的UA库(如fake_useragent),或手动维护常用浏览器UA列表。

4. 排查代理连接细节

虽然代理仪表盘显示连接正常,但需确认:

  • 代理是否传递了容器的异常特征(如hostname),可在Dockerfile中设置常规主机名:ENV HOSTNAME=desktop-abc123
  • 本地与容器的代理连接是否存在Keep-Alive差异,使用Session复用连接可减少此类问题

5. 对比请求指纹

用curl在本地和容器中分别发送请求,对比完整请求头和响应:

# 本地执行
curl -v -x http://PROXY_USER:PROXY_PASSWORD@p.webshare.io:80 https://kleinanzeigen.de -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"

# 容器内执行(先进入容器)
docker exec -it <container_id> bash
curl -v -x http://PROXY_USER:PROXY_PASSWORD@p.webshare.io:80 https://kleinanzeigen.de -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"

重点对比Accept、Accept-Encoding、Connection等头字段,以及TLS握手信息。

内容的提问来源于stack exchange,提问作者HCook886

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:08:10