您是否正在考虑在 Puppeteer 和 Selenium 之间选择哪种方式进行网页抓取?两者都是功能强大的浏览器自动化框架,正确的选择取决于您的特定抓取需求和可用资源。
为了帮助您做出明智的决定,我们在下表中重点介绍了 Puppeteer 和 Selenium 之间的主要区别。之后,我们将深入研究细节并为每个框架提供一个抓取示例,以展示它们从网页中提取数据的有效性。
标准 | 傀儡师 | 硒 |
---|---|---|
兼容语言 | 仅官方支持 JavaScript,但有非官方的 PHP 和 Python 端口 | Java、Python、C#、Ruby、PHP、JavaScript 和 Kotlin |
浏览器支持 | Chromium 和实验性 Firefox 支持 | Chrome、Safari、Firefox、Opera、Edge 和 Internet Explorer |
表现 | 60% 比 Selenium 更快 | 快速地 |
操作系统支持 | Windows、Linux 和 macOS | Windows、Linux、macOS 和 Solaris |
建筑学 | 具有无头浏览器实例的事件驱动架构 | Web 驱动程序上的 JSONWire 协议用于控制浏览器实例 |
先决条件 | JavaScript 包就足够了 | Selenium Bindings(针对所选的编程语言)和浏览器 Web 驱动程序 |
社区 | 与 Selenium 相比,社区规模较小 | 完善的文档和庞大的社区 |
让我们继续详细讨论这些库,并使用每个库执行抓取示例,以说明它们从网页提取数据的效率。
傀儡师
傀儡师 是一个 Node.js 库,提供高级 API 来通过 DevTools 协议控制 Chrome 或 Chromium。它旨在自动执行 Chrome 或 Chromium 中的任务,例如截取屏幕截图、生成 PDF 和浏览页面。
Puppeteer 还可以用于通过模拟用户交互(例如单击按钮、填写表格和验证显示的结果)来测试网页。
Puppeteer 的优势
- 使用方便:使用简单、直接。
- 与 Chromium 捆绑:无需额外设置。
- 无头模式:默认情况下以无头模式运行,但可以配置为以全浏览器模式运行。
- 事件驱动架构:消除了代码中手动睡眠调用的需要。
- 综合能力:可以截取屏幕截图、生成 PDF 并自动执行所有浏览器操作。
- 绩效管理:提供记录运行时和负载性能的工具来优化和调试您的抓取工具。
- SPA 爬取:能够抓取单页应用程序(SPA)并生成预渲染内容(服务器端渲染)。
- 剧本录制:允许通过使用 DevTools 控制台在浏览器上记录操作来创建 Puppeteer 脚本。
Puppeteer 的缺点
- 有限的浏览器支持:与 Selenium 相比,支持的浏览器较少。
- 专注于 JavaScript:主要支持 JavaScript,尽管也存在 Python 和 PHP 的非官方端口。
使用 Puppeteer 进行网页抓取的示例
让我们通过 Puppeteer 网络抓取教程来从 Danube 网站的犯罪和惊悚类别中提取内容。
多瑙河商店:犯罪和惊悚片
首先,导入 Puppeteer 模块并创建一个异步函数来运行 Puppeteer 代码:
const puppeteer = require('puppeteer');
async function main() {
// Launch a headless browser instance
const browser = await puppeteer.launch({ headless: true });
// Create a new page object
const page = await browser.newPage();
// Navigate to the target URL and wait until the loading finishes
await page.goto('https://danube-webshop.herokuapp.com/', { waitUntil: 'networkidle2' });
// Wait for the left-side bar to load
await page.waitForSelector('ul.sidebar-list');
// Click on the first element and wait for the navigation to finish
await Promise.all([
page.waitForNavigation(),
page.click("ul[class='sidebar-list'] > li > a"),
]);
// Wait for the book previews to load
await page.waitForSelector("li[class='preview']");
// Extract the book previews
const books = await page.evaluateHandle(
() => [...document.querySelectorAll("li[class='preview']")]
);
// Extract the relevant data using page.evaluate
const processed_data = await page.evaluate(elements => {
let data = [];
elements.forEach(element => {
let title = element.querySelector("div.preview-title").innerHTML;
let author = element.querySelector("div.preview-author").innerHTML;
let rating = element.querySelector("div.preview-details > p.preview-rating").innerHTML;
let price = element.querySelector("div.preview-details > p.preview-price").innerHTML;
let result = { title, author, rating, price };
data.push(result);
});
return data;
}, books);
// Print out the extracted data
console.log(processed_data);
// Close the page and browser respectively
await page.close();
await browser.close();
}
// Run the main function to scrape the data
main();
预期输出
运行代码时,输出应类似于以下内容:
[
{
title: 'Does the Sun Also Rise?',
author: 'Ernst Doubtingway',
rating: '★★★★☆',
price: '$9.95'
},
{
title: 'The Insiders',
author: 'E. S. Hilton',
rating: '★★★★☆',
price: '$9.95'
},
{
title: 'A Citrussy Clock',
author: 'Bethany Urges',
rating: '★★★★★',
price: '$9.95'
}
]
使用 Puppeteer 的另一个示例
除了从网页抓取数据外,Puppeteer 还可用于各种自动化任务。一个常见的用例是生成网页的 PDF。让我们来看一个使用 Puppeteer 从网页生成 PDF 的示例。
使用 Puppeteer 生成 PDF
步骤 1:导入 Puppeteer 并创建异步函数
const puppeteer = require('puppeteer');
async function generatePDF() {
// Launch a headless browser instance
const browser = await puppeteer.launch({ headless: true });
// Create a new page object
const page = await browser.newPage();
// Navigate to the target URL
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
// Generate a PDF from the web page
await page.pdf({
path: 'example.pdf', // Output file path
format: 'A4', // Paper format
printBackground: true, // Include background graphics
});
// Close the page and browser respectively
await page.close();
await browser.close();
}
// Run the function to generate the PDF
generatePDF();
附加 Puppeteer 选项
Puppeteer 提供了多种生成 PDF 的选项,您可以根据需要进行自定义。以下是您可以使用的一些选项:
path
:保存PDF的文件路径。format
:纸张格式(例如“A4”、“Letter”)。printBackground
:是否包含背景图形。landscape
: 设置true
用于横向。margin
:指定 PDF 的边距(顶部、右侧、底部、左侧)。
带有附加选项的示例:
const puppeteer = require('puppeteer');
async function generatePDF() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({
path: 'example.pdf',
format: 'A4',
printBackground: true,
landscape: true,
margin: {
top: '20px',
right: '20px',
bottom: '20px',
left: '20px',
},
});
await page.close();
await browser.close();
}
generatePDF();
示例输出
运行上述代码将创建一个名为 example.pdf
在当前目录中包含网页内容 https://example.com
.
Puppeteer 是一款多功能工具,可用于执行从抓取数据到生成 PDF 等各种 Web 自动化任务。它易于使用且功能强大,是自动化各种浏览器活动的绝佳选择。无论您是抓取数据、生成报告还是测试网页,Puppeteer 都能为您提供高效完成工作所需的工具。
硒
硒 是一款开源的端到端测试和 Web 自动化工具,常用于 Web 抓取。其主要组件包括 Selenium IDE、Selenium WebDriver 和 Selenium Grid。
- Selenium IDE:用于在自动化操作之前记录操作。
- 硒网络驱动程序:在浏览器中执行命令。
- 硒网格:启用并行执行。
硒的优点
- 使用方便:使用简单、直接。
- 语言支持:支持Python、Java、JavaScript、Ruby、C#等多种编程语言。
- 浏览器自动化:可以自动化 Firefox、Edge、Safari 等浏览器,甚至自定义 QtWebKit 浏览器。
- 可扩展性:可以使用具有不同浏览器设置的云服务器将 Selenium 扩展到数百个实例。
- 跨平台:可在 Windows、macOS 和 Linux 上运行。
硒的缺点
- 复杂的设置:Selenium 设置方法可能很复杂。
使用 Selenium 进行 Web 抓取的示例
与 Puppeteer 一样,让我们使用相同的目标网站进行 Selenium 网页抓取教程。我们将从 Danube 网站的犯罪和惊悚类别中提取图书预览。
多瑙河商店:犯罪和惊悚片
步骤 1:导入必要的模块并配置 Selenium
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
options = webdriver.ChromeOptions()
options.add_argument("--headless")
步骤 2:初始化 Chrome WebDriver
driver = webdriver.Chrome(options=options)
步骤 3:导航到目标网站
time.sleep(1)
crime_n_thrillers = driver.find_element(By.CSS_SELECTOR, "ul[class='sidebar-list'] > li")
crime_n_thrillers.click()
time.sleep(1)
books = driver.find_elements(By.CSS_SELECTOR, "div.shop-content li.preview")
步骤 4:单击犯罪和惊悚片类别并提取图书预览
time.sleep(1)
crime_n_thrillers = driver.find_element(By.CSS_SELECTOR, "ul[class='sidebar-list'] > li")
crime_n_thrillers.click()
time.sleep(1)
books = driver.find_elements(By.CSS_SELECTOR, "div.shop-content li.preview")
步骤 5:定义一个函数来从每个图书预览中提取数据
def extract(element):
title = element.find_element(By.CSS_SELECTOR, "div.preview-title").text
author = element.find_element(By.CSS_SELECTOR, "div.preview-author").text
rating = element.find_element(By.CSS_SELECTOR, "div.preview-details p.preview-rating").text
price = element.find_element(By.CSS_SELECTOR, "div.preview-details p.preview-price").text
return {"title": title, "author": author, "rating": rating, "price": price}
步骤 6:循环预览、提取数据并退出驱动程序
extracted_data = []
for element in books:
data = extract(element)
extracted_data.append(data)
print(extracted_data)
driver.quit()
预期输出
运行上述代码将产生类似以下内容的输出:
[
{'title': 'Does the Sun Also Rise?', 'author': 'Ernst Doubtingway', 'rating': '★★★★☆', 'price': '$9.95'},
{'title': 'The Insiders', 'author': 'E. S. Hilton', 'rating': '★★★★☆', 'price': '$9.95'},
{'title': 'A Citrussy Clock', 'author': 'Bethany Urges', 'rating': '★★★★★', 'price': '$9.95'}
]
附加 Selenium 示例:截屏
除了抓取数据之外,Selenium 还可用于截取网页截图。下面是使用 Selenium 截取网页截图的示例。
步骤 1:导入必要的模块并配置 Selenium
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless")
步骤 2:初始化 Chrome WebDriver
driver = webdriver.Chrome(options=options)
步骤 3:导航到目标网站
url = "https://example.com"
driver.get(url)
步骤 4:截屏
driver.save_screenshot("example_screenshot.png")
步骤 5:退出驱动程序
driver.quit()
Selenium 是一款多功能工具,可用于执行网页自动化任务,包括网页抓取和截屏。它支持多种编程语言和浏览器,并且可扩展,是满足各种自动化需求的强大选择。无论您是提取数据还是生成报告,Selenium 都能提供高效自动化任务的功能。
Puppeteer 与 Selenium:速度比较
Puppeteer 比 Selenium 快吗?答案是肯定的 — Puppeteer 通常比 Selenium 快。
为了比较 Puppeteer 和 Selenium 的速度,我们使用了 Danube-store 沙箱并运行了上述脚本 20 次,并计算了平均执行时间。
硒速度测试
我们使用了 time
使用 Python 中的模块来测量 Selenium 脚本的执行时间。在脚本开始时记录开始时间,在脚本结束时记录结束时间。这两个时间之间的差值就是总执行时长。
以下是用于 Selenium 的完整脚本:
import time
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
def extract(element):
title = element.find_element(By.CSS_SELECTOR, "div.preview-title").text
author = element.find_element(By.CSS_SELECTOR, "div.preview-author").text
rating = element.find_element(By.CSS_SELECTOR, "div.preview-details p.preview-rating").text
price = element.find_element(By.CSS_SELECTOR, "div.preview-details p.preview-price").text
return {"title": title, "author": author, "rating": rating, "price": price}
# Start the timer
start_time = time.time()
options = webdriver.ChromeOptions()
options.add_argument("--headless")
# Create a new instance of the Chrome driver
driver = webdriver.Chrome(options=options)
url = "https://danube-webshop.herokuapp.com/"
driver.get(url)
# Click on the Crime & Thrillers category
time.sleep(1)
crime_n_thrillers = driver.find_element(By.CSS_SELECTOR, "ul[class='sidebar-list'] > li")
crime_n_thrillers.click()
time.sleep(1)
# Extract the book previews
books = driver.find_elements(By.CSS_SELECTOR, "div.shop-content li.preview")
extracted_data = []
for element in books:
data = extract(element)
extracted_data.append(data)
print(extracted_data)
# End the timer
end_time = time.time()
print(f"The whole script took: {end_time - start_time:.4f} seconds")
driver.quit()
木偶速度测试
对于 Puppeteer 脚本,我们使用了 Date
对象来测量执行时间。在脚本开始时记录开始时间,在脚本结束时记录结束时间。这两个时间之间的差值就是总执行时长。
以下是 Puppeteer 使用的完整脚本:
const puppeteer = require('puppeteer');
async function main() {
const start = Date.now();
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://danube-webshop.herokuapp.com/', { waitUntil: 'networkidle2' });
await page.waitForSelector('ul.sidebar-list');
await Promise.all([
page.waitForNavigation(),
page.click("ul[class='sidebar-list'] > li > a"),
]);
await page.waitForSelector("li[class='preview']");
const books = await page.evaluateHandle(
() => [...document.querySelectorAll("li[class='preview']")]
);
const processed_data = await page.evaluate(elements => {
let data = [];
elements.forEach(element => {
let title = element.querySelector("div.preview-title").innerHTML;
let author = element.querySelector("div.preview-author").innerHTML;
let rating = element.querySelector("div.preview-details > p.preview-rating").innerHTML;
let price = element.querySelector("div.preview-details > p.preview-price").innerHTML;
let result = { title, author, rating, price };
data.push(result);
});
return data;
}, books);
console.log(processed_data);
await page.close();
await browser.close();
const end = Date.now();
console.log(`Execution time: ${(end - start) / 1000} seconds`);
}
main();
性能测试结果
性能测试显示,Puppeteer 比 Selenium 快约 60%。这种速度优势使 Puppeteer 成为需要高速网页抓取和自动化的项目的更合适选择,尤其是在使用基于 Chromium 的浏览器时。
速度结果摘要:
下图说明了 Puppeteer 和 Selenium 之间的性能差异:
在这种情况下,对于需要快速、高效的网络抓取的项目来说,扩展 Puppeteer 应用程序是最佳选择。
Puppeteer 与 Selenium:哪个更好?
那么,Selenium 和 Puppeteer 哪个更适合抓取数据呢?这个问题没有直接的答案,因为它取决于多种因素,例如长期库支持、跨浏览器支持以及您的网页抓取需求。
Puppeteer 速度更快,但与 Selenium 相比,它支持的浏览器较少。与 Puppeteer 相比,Selenium 还支持更多的编程语言。
结论
尽管使用 Puppeteer 或 Selenium 进行网页抓取是一个不错的选择,但扩展和优化网页抓取项目可能具有挑战性,因为高级反机器人措施可以检测并阻止这些库。避免这种情况的最佳方法是使用网页抓取 API,例如 OneProxy。
将 Puppeteer 与代理服务器结合使用
要将 Puppeteer 与代理服务器一起使用,您可以在 args
启动浏览器实例时选项。以下是示例:
const puppeteer = require('puppeteer');
async function main() {
const proxyServer = 'http://your-proxy-server:port';
const browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${proxyServer}`]
});
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
// Perform your web scraping tasks here
await browser.close();
}
main();
将 Selenium 与代理服务器结合使用
要将 Selenium 与代理服务器一起使用,可以使用 webdriver.Proxy
类。下面是一个例子:
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "your-proxy-server:port"
proxy.ssl_proxy = "your-proxy-server:port"
capabilities = webdriver.DesiredCapabilities.CHROME
proxy.add_to_capabilities(capabilities)
options = webdriver.ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome(desired_capabilities=capabilities, options=options)
driver.get("https://example.com")
# Perform your web scraping tasks here
driver.quit()
使用带有 Puppeteer 和 Selenium 的代理服务器可以帮助绕过基于 IP 的限制并降低被阻止的风险,从而提高您的网络抓取任务的效率。 OneProxy 的轮换代理 可以进一步优化这一过程,提供无缝的抓取体验。