Python 爬虫 403 错误处理:Selenium 与普通请求对比

3 阅读6分钟

一、Python 爬虫 403 错误的核心成因

403 Forbidden 本质是服务器对请求的「身份校验失败」,常见触发原因可分为以下几类:

  1. 请求头缺失或异常:服务器会校验 User-Agent、Referer、Cookie 等关键请求头,若缺失或为默认值(如 Python-urllib/3.8),会被判定为爬虫;
  2. IP 封禁:同一 IP 短时间内高频请求,被服务器加入黑名单;
  3. 反爬机制检测:网站通过 JS 加密、验证码、浏览器指纹(如 navigator 对象)等识别非人工访问;
  4. 会话验证失败:部分网站需要先登录生成有效会话,无会话请求会直接返回 403。

普通 HTTP 请求(requests 库)和 Selenium 的核心差异,本质是「模拟请求」与「模拟真实浏览器行为」的区别,这也决定了二者处理 403 的能力边界。

二、普通请求(requests)vs Selenium:核心差异对比

表格

维度普通请求(requests)Selenium
请求本质构造 HTTP/HTTPS 请求包,无浏览器环境驱动真实浏览器(Chrome/Firefox),模拟人工操作
请求头特征需手动构造,易被识别为非浏览器请求自动携带浏览器原生请求头,更接近真实用户
JS 渲染能力无,无法处理动态加载内容支持完整 JS 渲染,可绕过 JS 反爬
浏览器指纹检测无指纹,易被识别有完整浏览器指纹,不易被检测
性能轻量,请求速度快重量级,启动浏览器耗时,请求效率低
反爬绕过难度高,需手动破解各类反爬规则低,天然模拟人工行为,绕过基础反爬更简单

简言之:requests 适合爬取反爬较弱的静态页面,处理 403 需手动「伪装」请求;Selenium 适合爬取反爬严格的动态页面,通过模拟真实浏览器天然降低 403 概率,但牺牲了性能。

三、实战:处理 403 错误的代码实现

场景 1:requests 处理 403 错误(手动伪装请求)

核心思路

通过完善请求头、添加延时、使用代理 IP 等方式,模拟真实浏览器请求,绕过服务器的基础校验。

python

运行

import requests
import time
from fake_useragent import UserAgent  # 需额外安装:pip install fake-useragent

def requests_crawl(url):
    # 1. 构造模拟浏览器的请求头
    ua = UserAgent()
    headers = {
        "User-Agent": ua.chrome,  # 随机生成 Chrome 浏览器 UA
        "Referer": url.split("/")[0] + "//" + url.split("/")[2],  # 构造 Referer,模拟从本站跳转
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1"
    }
    
    # 2. 配置代理信息(使用指定的带认证代理)
    proxyHost = "www.16yun.cn"
    proxyPort = "5445"
    proxyUser = "16QMSOML"
    proxyPass = "280651"
    
    # 构造带用户名密码认证的代理链接
    proxy_auth = f"{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
    proxies = {
        "http": f"http://{proxy_auth}",
        "https": f"http://{proxy_auth}"  # https请求也走http代理通道
    }
    
    try:
        # 3. 发送请求(添加延时,避免高频)
        time.sleep(1)  # 每次请求间隔 1 秒
        response = requests.get(
            url=url,
            headers=headers,
            proxies=proxies,
            timeout=10,
            allow_redirects=True  # 允许重定向,部分 403 是临时重定向导致
        )
        
        # 4. 校验响应状态
        if response.status_code == 200:
            print("Requests 爬取成功,响应长度:", len(response.text))
            return response.text
        elif response.status_code == 403:
            print("Requests 仍返回 403,需升级方案(如 Selenium)")
            return None
        else:
            print(f"Requests 请求失败,状态码:{response.status_code}")
            return None
            
    except Exception as e:
        print(f"Requests 请求异常:{str(e)}")
        return None

# 测试调用
if __name__ == "__main__":
    target_url = "https://example.com/test"  # 替换为实际目标 URL
    requests_crawl(target_url)

关键说明

  • <font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">fake-useragent</font> 库用于生成随机真实的 User-Agent,避免固定 UA 被识别;
  • Referer 需与目标域名一致,模拟从本站内跳转的请求;
  • 代理 IP 和延时是避免 IP 封禁的核心手段,高频请求下必须添加;
  • 若仍返回 403,说明网站启用了更严格的反爬(如 JS 验证、浏览器指纹检测),需切换 Selenium。

场景 2:Selenium 处理 403 错误(模拟真实浏览器)

核心思路

通过驱动真实 Chrome 浏览器,自动携带浏览器原生请求头,绕过 JS 验证和浏览器指纹检测,从根本上降低 403 概率。

python

运行

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
import time

def selenium_crawl(url):
    # 1. 配置 Chrome 选项,模拟真实浏览器
    chrome_options = Options()
    # 禁用自动化提示(关键:避免被网站检测到 Selenium)
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    # 禁用图片/视频加载,提升速度
    chrome_options.add_experimental_option("prefs", {
        "profile.managed_default_content_settings.images": 2,
        "profile.managed_default_content_settings.video": 2
    })
    # 添加启动参数,进一步伪装
    chrome_options.add_argument("--disable-blink-features=AutomationControlled")
    chrome_options.add_argument("--disable-dev-shm-usage")  # 解决容器环境内存不足问题
    chrome_options.add_argument("--no-sandbox")  # 禁用沙箱模式
    chrome_options.add_argument("--headless=new")  # 无头模式(无浏览器窗口),注释可显示窗口
    # 随机 UA(也可省略,浏览器会自动携带原生 UA)
    chrome_options.add_argument(f"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
    
    # 2. 初始化浏览器驱动
    try:
        service = Service(ChromeDriverManager().install())
        driver = webdriver.Chrome(service=service, options=chrome_options)
        
        # 3. 执行 JS 移除 webdriver 标识(关键:绕过浏览器指纹检测)
        driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
        
        # 4. 访问目标 URL
        driver.get(url)
        time.sleep(2)  # 等待页面加载完成
        
        # 5. 校验响应状态(Selenium 无法直接获取状态码,通过页面内容判断)
        page_source = driver.page_source
        if "403 Forbidden" in page_source:
            print("Selenium 仍返回 403,需检查代理/登录状态")
        else:
            print("Selenium 爬取成功,页面长度:", len(page_source))
        
        # 6. 关闭浏览器
        driver.quit()
        return page_source
        
    except Exception as e:
        print(f"Selenium 请求异常:{str(e)}")
        return None

# 测试调用
if __name__ == "__main__":
    target_url = "https://example.com/test"  # 替换为实际目标 URL
    selenium_crawl(target_url)

关键说明

  • <font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">excludeSwitches</font><font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">disable-blink-features</font> 是核心:移除 Selenium 的自动化标识,避免被网站检测;
  • 无头模式(<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">--headless=new</font>)适合服务器运行,注释后可显示浏览器窗口调试;
  • Selenium 无法直接获取 HTTP 状态码,需通过页面内容(如是否包含「403 Forbidden」)判断是否爬取成功;
  • 若仍返回 403,需进一步添加代理 IP、登录会话(通过 Cookie 或手动登录)。

四、方案选择与优化建议

  1. 优先使用 requests:若目标网站反爬较弱(仅校验请求头),requests 性能更高,通过完善请求头、添加延时即可解决 403;
  2. 切换 Selenium:若 requests 多次尝试仍返回 403,且网站包含动态 JS 渲染,Selenium 是更优解;
  3. 混合方案:用 Selenium 获取登录 Cookie / 会话,再用 requests 携带 Cookie 请求,兼顾性能与反爬能力;
  4. 进阶优化
    • 避免单一 IP 高频请求,使用代理池轮换 IP;
    • 针对严格反爬网站,可搭配 undetected-chromedriver(替代原生 ChromeDriver),进一步隐藏 Selenium 特征;
    • 添加随机延时(如 1-3 秒),模拟人工操作节奏。

五、注意事项

  1. 遵守网站 <font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">robots.txt</font> 协议,避免过度爬取给服务器造成压力;
  2. 部分网站的反爬机制受法律保护,爬取前需确认合规性;
  3. Selenium 版本需与浏览器版本匹配,推荐使用 <font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">webdriver-manager</font> 自动管理驱动版本。

总结

  1. Python 爬虫 403 错误的核心是服务器的身份校验失败,普通请求(requests)需手动伪装请求头、添加代理,而 Selenium 通过模拟真实浏览器天然降低 403 概率;
  2. requests 适合反爬较弱的静态页面,性能更高;Selenium 适合反爬严格的动态页面,上手更简单但性能较低;
  3. 处理 403 的关键是「模拟真实用户行为」:requests 靠手动构造请求头,Selenium 靠隐藏自动化标识、模拟浏览器操作。