构建混合爬虫:何时使用Requests,何时切换至Selenium处理请求头?

一、核心理念:为什么不能"一把梭"?

在做出选择之前,我们必须理解两者的工作原理。

1. Requests:纯粹的网络请求库

  • 本质:模拟HTTP请求,直接与服务器交互。它轻量、高效,一个请求一个响应,干净利落。
  • 请求头处理 :你可以通过<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">headers</font>参数完全、精确地控制 发送给服务器的每一个请求头。无论是<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">User-Agent</font>, <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Cookie</font>, <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Referer</font>,还是自定义的认证头,都可以轻松设置。
  • 优势:速度极快,资源消耗低,是处理大规模数据采集的首选。
  • 劣势 :无法执行JavaScript。对于依赖JS渲染的动态网页,<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font>获取到的HTML源码是不完整的。

2. Selenium:浏览器自动化工具

  • 本质:启动并控制一个真实的浏览器(如Chrome, Firefox)。你看到的是什么,它获取的就是什么。
  • 请求头处理 :在初始阶段,你可以通过<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">ChromeOptions.add_argument()</font>来设置一些基本的请求头,如<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">--user-agent</font>。对于更精细的请求头控制,则需要借助更高级的CDP浏览器插件/中间件,过程相对繁琐。
  • 优势:能完美渲染JavaScript,模拟所有用户交互行为(点击、输入、滚动等)。
  • 劣势:速度慢,资源消耗巨大(CPU和内存),容易被网站通过浏览器指纹识别。

二、决策时刻:何时用Requests?何时切Selenium?

基于以上理解,我们可以得出清晰的决策逻辑图:

坚定不移地使用 Requests:

  • 目标数据在页面初始HTML中,无需JS加载。
  • 网站主要通过请求头(如<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Authorization</font>, <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Tokens</font>)进行反爬,你需要精确伪造。
  • 需要进行高频、快速的API接口调用。

果断切换至 Selenium:

  • 目标数据由JavaScript动态渲染/异步加载(如通过Ajax)。
  • 需要与页面进行复杂交互后才能获取数据(如登录、翻页、下拉)。
  • 网站使用了复杂的浏览器环境检测。

混合策略的精髓:
用Selenium做"钥匙",用Requests做"收割机" 。让Selenium去完成那些需要浏览器环境才能完成的"脏活累活"(如登录、获取Cookie、触发JS),然后将其获得的关键身份凭证(如Cookies)和构造好的请求头,交给高效的Requests去进行大规模的数据请求。

三、实战构建:混合爬虫处理需要登录的网站

假设我们要爬取一个网站<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">https://example.com/data</font>,该网站需要登录,且数据列表由JS渲染。

我们的策略是:

  1. 使用<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Selenium</font>模拟登录,获取登录后的Cookies和关键请求头。
  2. 将这些Cookies和请求头移植到<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font>的会话中。
  3. 使用<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font>去请求数据API,高效获取数据。
步骤1:使用Selenium完成登录

python

plain 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

def login_with_selenium():
    """使用Selenium模拟登录,并返回关键的Cookies和User-Agent"""
    print("启动Selenium进行登录...")
    
    # 配置浏览器选项(可选:无头模式)
    options = webdriver.ChromeOptions()
    # options.add_argument('--headless') # 生产环境可开启
    options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36')
    
    driver = webdriver.Chrome(options=options)
    
    try:
        # 访问登录页面
        driver.get('https://example.com/login')
        
        # 显式等待,找到用户名和密码输入框
        username_input = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "username"))
        )
        password_input = driver.find_element(By.ID, "password")
        
        # 输入凭据并提交
        username_input.send_keys("your_username")
        password_input.send_keys("your_password")
        driver.find_element(By.ID, "login-btn").click()
        
        # 等待登录成功,例如等待某个登录后才出现的元素
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "user-dashboard"))
        )
        print("登录成功!")
        
        # 关键步骤:获取登录后的Cookies和浏览器实际的User-Agent
        cookies = driver.get_cookies()
        user_agent = driver.execute_script("return navigator.userAgent;")
        
        return cookies, user_agent
        
    finally:
        # 关闭浏览器
        driver.quit()

# 执行登录函数
selenium_cookies, selenium_user_agent = login_with_selenium()
步骤2:将Selenium的"状态"移植到Requests

python

plain 复制代码
import requests

def create_requests_session(cookies, user_agent):
    """创建一个携带了Selenium状态的Requests会话"""
    session = requests.Session()
    
    # 1. 设置User-Agent
    session.headers.update({
        'User-Agent': user_agent,
        # 可以在这里添加其他在Selenium中观察到的固定请求头
        'Referer': 'https://example.com/',
        'Accept': 'application/json, text/plain, */*' # 根据实际情况修改
    })
    
    # 2. 处理Cookies:将Selenium的cookies格式转换为Requests可用的格式
    requests_cookies = {}
    for cookie in cookies:
        requests_cookies[cookie['name']] = cookie['value']
        
    # 将cookies更新到会话中
    session.cookies.update(requests_cookies)
    
    return session

# 创建混合爬虫会话
hybrid_session = create_requests_session(selenium_cookies, selenium_user_agent)
步骤3:使用Requests进行高效数据爬取

现在,我们可以用这个<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">hybrid_session</font>去请求数据接口了。这个接口可能是一个返回JSON的API。

python

plain 复制代码
dimport requests

# 代理配置信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"

def create_requests_session_with_proxy(cookies, user_agent):
    """创建一个携带了Selenium状态和代理配置的Requests会话"""
    session = requests.Session()
    
    # 设置代理
    proxies = {
        'http': f'http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}',
        'https': f'http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}'
    }
    session.proxies.update(proxies)
    
    # 设置User-Agent和其他请求头
    session.headers.update({
        'User-Agent': user_agent,
        'Referer': 'https://example.com/',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Connection': 'keep-alive'
    })
    
    # 处理Cookies
    requests_cookies = {}
    for cookie in cookies:
        requests_cookies[cookie['name']] = cookie['value']
    session.cookies.update(requests_cookies)
    
    return session

# 使用带代理的Session创建函数
hybrid_session_with_proxy = create_requests_session_with_proxy(selenium_cookies, selenium_user_agent)

def fetch_data_with_proxy_session(session):
    """使用已经配置好代理的会话请求数据"""
    api_url = "https://example.com/api/data-list"
    
    try:
        # 直接使用session,代理已经在session中配置好了
        response = session.get(api_url, timeout=30)
        response.raise_for_status()
        
        data = response.json()
        print(f"成功获取到 {len(data.get('items', []))} 条数据。")
        
        for item in data['items']:
            print(f"处理数据: {item['id']} - {item['title']}")
            
        return data
        
    except requests.exceptions.RequestException as e:
        print(f"请求数据时发生错误: {e}")
        return None

# 执行数据抓取
data = fetch_data_with_proxy_session(hybrid_session_with_proxy)

四、策略进阶与注意事项

  1. 请求头同步 :除了<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">User-Agent</font><font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Cookies</font>,确保其他重要请求头(如<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Referer</font>, <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Accept-Language</font>等)在<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font>会话中也保持一致。使用浏览器的开发者工具(Network面板)仔细检查。
  2. 会话保持<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests.Session()</font>对象会自动处理Cookies的更新。如果后续请求会更新Cookies,这个会话会保持住状态。
  3. 错误处理与重试 :在<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">fetch_data_with_requests</font>函数中,加入重试机制。如果请求失败(可能是Cookie过期),可以触发一个信号,让混合爬虫重新执行<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">login_with_selenium</font>流程。
  4. 性能对比:在同一任务上,混合爬虫的速度通常比纯Selenium方案快5-10倍甚至更多,因为避免了所有浏览器的渲染开销。

结论

构建混合爬虫的核心思想是扬长避短,物尽其用 。通过理解<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font><font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Selenium</font>在处理请求头和页面渲染上的根本差异,我们能够做出最明智的技术选型。

  • **<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Requests</font>**是你的特种部队,精准、高效,负责主要的数据攻坚任务。
  • **<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">Selenium</font>**是你的工程兵,能处理复杂地形(JS交互),为特种部队扫清障碍(获取认证信息)。
相关推荐
2401_827560201 小时前
【Python脚本系列】PyAudio+librosa+dtw库录制、识别音频并实现点击(四)
python·语音识别
BBB努力学习程序设计2 小时前
Python自动化脚本:告别重复劳动
python·pycharm
BBB努力学习程序设计2 小时前
Python函数式编程:优雅的代码艺术
python·pycharm
2501_940943912 小时前
体系课\ Python Web全栈工程师
开发语言·前端·python
田姐姐tmner2 小时前
Python切片
开发语言·python
4***72132 小时前
网络爬虫学习:借助DeepSeek完善爬虫软件,实现模拟鼠标右键点击,将链接另存为本地文件
爬虫·学习·计算机外设
t***31653 小时前
爬虫学习案例3
爬虫·python·学习
Hacker_Fuchen3 小时前
POST请求提交数据的三种方式及通过Postman实现
自动化测试·软件测试·测试工具·postman
AI小云3 小时前
【数据操作与可视化】Pandas数据处理-其他操作
python·pandas