
Selenium本身是一个自动化测试工具,用于模拟真实用户操作。直接使用它来爬虫可能会很慢。提升效率的关键在于,将其从“模拟视觉化用户”转变为“高性能的无头数据采集工具”。
Requests库无法获取完整内容。Selenium可以驱动浏览器完整执行JS,直接获取最终渲染的DOM。以下示例均使用 Selenium + Chrome 无头模式。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
import zipfile
# 代理信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
# 创建Chrome选项
chrome_options = Options()
# 创建代理认证插件
def create_proxy_auth_extension(proxy_host, proxy_port, proxy_username, proxy_password, scheme='http'):
"""创建带有代理认证的Chrome扩展"""
# 插件配置
manifest_json = """
{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
"""
background_js = """
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "%s",
host: "%s",
port: parseInt(%s)
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
chrome.webRequest.onAuthRequired.addListener(
function(details) {
return {
authCredentials: {
username: "%s",
password: "%s"
}
};
},
{urls: ["<all_urls>"]},
['blocking']
);
""" % (scheme, proxy_host, proxy_port, proxy_username, proxy_password)
# 创建临时插件文件
import tempfile
import os
from pathlib import Path
plugin_dir = tempfile.mkdtemp()
plugin_file = Path(plugin_dir) / "proxy_auth_plugin.zip"
with zipfile.ZipFile(plugin_file, 'w') as zp:
zp.writestr("manifest.json", manifest_json)
zp.writestr("background.js", background_js)
return plugin_file
# 创建代理认证插件
proxy_plugin = create_proxy_auth_extension(
proxy_host=proxyHost,
proxy_port=proxyPort,
proxy_username=proxyUser,
proxy_password=proxyPass
)
# 添加插件到Chrome选项
chrome_options.add_extension(proxy_plugin)
# 核心:启用无头模式
chrome_options.add_argument("--headless=new")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=1920,1080")
# 可选:禁用图片加载
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_options.add_experimental_option("prefs", prefs)
# 初始化驱动
driver = webdriver.Chrome(options=chrome_options)
try:
# 测试代理是否生效
driver.get("https://httpbin.org/ip")
page_source = driver.page_source
print(page_source)
print("代理设置成功!")
# 您的实际爬虫代码
# driver.get("https://example.com")
# ... 其他操作
finally:
driver.quit()
# 清理临时文件
import os
import shutil
plugin_dir = os.path.dirname(proxy_plugin)
if os.path.exists(plugin_dir):
shutil.rmtree(plugin_dir)固定使用time.sleep()是效率低下的主要原因。应使用显式等待。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.get("https://example.com/dynamic-content")
try:
# 显式等待:最多等10秒,直到指定元素出现在DOM中
# 一旦元素出现,立即继续执行,无需等待完10秒
target_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "dynamic-content-list"))
)
# 对找到的元素进行操作
items = target_element.find_elements(By.TAG_NAME, "li")
for item in items:
print(item.text)
except Exception as e:
print("元素未在指定时间内加载出来:", e)有时,数据直接保存在页面的JS变量中,直接提取比解析HTML更高效。
# 假设页面有一个JS变量:var userData = {name: "John", id: 123};
user_data = driver.execute_script("return window.userData;")
print(user_data) # 直接得到Python字典:{'name': 'John', 'id': 123}
# 或者,用JS进行复杂的DOM查询或操作
all_links_text = driver.execute_script("""
var links = Array.from(document.querySelectorAll('a'));
return links.map(link => link.textContent);
""")
print(all_links_text)concurrent.futures.ThreadPoolExecutor管理多个浏览器实例。selenium-grid进行分布式爬取。规避检测:
selenium-stealth等库来隐藏Selenium的特征。from selenium_stealth import stealth
# ... 驱动初始化后
stealth(driver,
languages=["en-US", "en"],
vendor="Google Inc.",
platform="Win32",
webgl_vendor="Intel Inc.",
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)try-except块并实现重试逻辑。操作 | 低效做法 | 高效做法 |
|---|---|---|
浏览器模式 | 使用有图形界面的浏览器 | 使用Chrome/Firefox无头模式 |
等待方式 | 大量使用time.sleep(n) | 使用WebDriverWait显式等待 |
资源加载 | 加载所有图片、CSS、字体 | 禁用图片加载,可选择性阻塞不必要资源 |
驱动管理 | 每次任务都创建/销毁驱动 | 考虑使用驱动池(需自行实现) |
数据提取 | 仅通过page_source然后解析 | 结合execute_script直接从JS上下文获取 |
并发 | 单线程顺序爬取 | 多线程/分布式(Selenium Grid) |
最终建议:虽然Selenium功能强大,但它始终是资源密集型工具。在爬虫项目中,应遵循 “首选轻量级,不得已再用Selenium” 的原则。首先尝试分析网站的API接口(通过浏览器开发者工具的“网络”面板),能用Requests模拟API调用是速度最快、最稳定的方案。当面对纯JS渲染、且没有清晰API的网站时,Selenium配合无头浏览器才是你的终极武器。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。