首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >构建混合爬虫:何时使用Requests,何时切换至Selenium处理请求头?

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

原创
作者头像
小白学大数据
发布2025-11-26 16:51:52
发布2025-11-26 16:51:52
190
举报

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

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

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

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

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

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

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

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

坚定不移地使用 Requests:

  • 目标数据在页面初始HTML中,无需JS加载。
  • 网站主要通过请求头(如Authorization, Tokens)进行反爬,你需要精确伪造。
  • 需要进行高频、快速的API接口调用。

果断切换至 Selenium:

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

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

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

假设我们要爬取一个网站https://example.com/data,该网站需要登录,且数据列表由JS渲染。

我们的策略是:

  1. 使用Selenium模拟登录,获取登录后的Cookies和关键请求头。
  2. 将这些Cookies和请求头移植到Requests的会话中。
  3. 使用Requests去请求数据API,高效获取数据。
步骤1:使用Selenium完成登录

python

代码语言:txt
复制
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

代码语言:txt
复制
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进行高效数据爬取

现在,我们可以用这个hybrid_session去请求数据接口了。这个接口可能是一个返回JSON的API。

python

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

结论

构建混合爬虫的核心思想是扬长避短,物尽其用。通过理解RequestsSelenium在处理请求头和页面渲染上的根本差异,我们能够做出最明智的技术选型。

  • Requests是你的特种部队,精准、高效,负责主要的数据攻坚任务。
  • Selenium是你的工程兵,能处理复杂地形(JS交互),为特种部队扫清障碍(获取认证信息)。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心理念:为什么不能“一把梭”?
  • 二、决策时刻:何时用Requests?何时切Selenium?
  • 三、实战构建:混合爬虫处理需要登录的网站
    • 步骤1:使用Selenium完成登录
    • 步骤2:将Selenium的“状态”移植到Requests
    • 步骤3:使用Requests进行高效数据爬取
  • 四、策略进阶与注意事项
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档