
在做出选择之前,我们必须理解两者的工作原理。
1. Requests:纯粹的网络请求库
headers参数完全、精确地控制发送给服务器的每一个请求头。无论是User-Agent, Cookie, Referer,还是自定义的认证头,都可以轻松设置。Requests获取到的HTML源码是不完整的。2. Selenium:浏览器自动化工具
ChromeOptions.add_argument()来设置一些基本的请求头,如--user-agent。对于更精细的请求头控制,则需要借助更高级的CDP或浏览器插件/中间件,过程相对繁琐。基于以上理解,我们可以得出清晰的决策逻辑图:
坚定不移地使用 Requests:
Authorization, Tokens)进行反爬,你需要精确伪造。果断切换至 Selenium:
混合策略的精髓: 用Selenium做“钥匙”,用Requests做“收割机”。让Selenium去完成那些需要浏览器环境才能完成的“脏活累活”(如登录、获取Cookie、触发JS),然后将其获得的关键身份凭证(如Cookies)和构造好的请求头,交给高效的Requests去进行大规模的数据请求。
假设我们要爬取一个网站https://example.com/data,该网站需要登录,且数据列表由JS渲染。
我们的策略是:
Selenium模拟登录,获取登录后的Cookies和关键请求头。Requests的会话中。Requests去请求数据API,高效获取数据。python
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()python
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)现在,我们可以用这个hybrid_session去请求数据接口了。这个接口可能是一个返回JSON的API。
python
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)User-Agent和Cookies,确保其他重要请求头(如Referer, Accept-Language等)在Requests会话中也保持一致。使用浏览器的开发者工具(Network面板)仔细检查。Requests.Session()对象会自动处理Cookies的更新。如果后续请求会更新Cookies,这个会话会保持住状态。fetch_data_with_requests函数中,加入重试机制。如果请求失败(可能是Cookie过期),可以触发一个信号,让混合爬虫重新执行login_with_selenium流程。构建混合爬虫的核心思想是扬长避短,物尽其用。通过理解Requests和Selenium在处理请求头和页面渲染上的根本差异,我们能够做出最明智的技术选型。
Requests是你的特种部队,精准、高效,负责主要的数据攻坚任务。Selenium是你的工程兵,能处理复杂地形(JS交互),为特种部队扫清障碍(获取认证信息)。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。