运行时依赖
安装命令
点击复制技能文档
浏览器自动化
Puppeteer驱动的网页抓取和浏览器自动化。当使用此技能时:
✅ 使用此技能时:
“从 [URL] 抓取数据”
“从 [网站] 提取所有 [产品/列表/项目]”
“截取 [页面] 的截图”
“爬取 [网站] 并收集 [信息]”
“填写并提交 [表单]”
任何需要浏览器渲染的JavaScript内容
❌ 不要使用此技能时:
简单的静态页面 → 使用 web_fetch 代替
可用的API → 直接使用 fetch API
受限速率的网站 → 尊重 robots.txt
快速入门
# 安装 Puppeteer
npm install puppeteer
# 基本抓取
node scripts/scrape.js https://example.com
核心模式
启动浏览器
const puppeteer = require('puppeteer');
async function scrape(url) {
const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// ... 提取数据 ...
await browser.close();
}
提取文本内容
// 获取选择器的所有文本
const titles = await page.$$eval('h2', els => els.map(el => el.textContent.trim()));
// 获取单个元素的文本
const price = await page.$eval('.price', el => el.textContent.trim());
提取 HTML
const html = await page.$eval('.product-list', el => el.innerHTML);
提取属性
const links = await page.$$eval('a', els => els.map(el => ({ text: el.textContent.trim(), href: el.getAttribute('href') })));
等待内容
// 等待选择器
await page.waitForSelector('.results', { timeout: 10000 });
// 等待网络空闲
await page.goto(url, { waitUntil: 'networkidle2' });
// 等待函数
await page.waitForFunction(() => document.querySelectorAll('.item').length > 10);
分页
async function scrapeWithPagination(baseUrl, maxPages = 5) {
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
let results = [];
for (let i = 1; i <= maxPages; i++) {
const url = ${baseUrl}?page=${i};
await page.goto(url, { waitUntil: 'networkidle2' });
const items = await page.$$eval('.item', els => els.map(el => el.textContent.trim()) );
if (items.length === 0) break;
results.push(...items);
}
await browser.close();
return results;
}
截图
// 全页截图
await page.screenshot({ path: 'screenshot.png', fullPage: true });
// 元素截图
const element = await page.$('.chart');
await element.screenshot({ path: 'chart.png' });
阻止资源(加速)
await page.setRequestInterception(true);
page.on('request', req => {
if (['image', 'stylesheet', 'font'].includes(req.resourceType())) {
req.abort();
} else {
req.continue();
}
});
脚本
scrape.js — 基本抓取
// 使用方法:node scripts/scrape.js [选择器]
const puppeteer = require('puppeteer');
const url = process.argv[2];
const selector = process.argv[3] || 'body';
if (!url) {
console.error('使用方法:node scrape.js [选择器]');
process.exit(1);
}
(async () => {
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
const content = await page.$$eval(selector, els => els.map(el => el.textContent.trim()) );
console.log(JSON.stringify(content, null, 2));
await browser.close();
})();
screenshot.js — 页面截图
// 使用方法:node scripts/screenshot.js [输出.png]
const puppeteer = require('puppeteer');
const url = process.argv[2];
const output = process.argv[3] || 'screenshot.png';
if (!url) {
console.error('使用方法:node screenshot.js [输出.png]');
process.exit(1);
}
(async () => {
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
await page.screenshot({ path: output, fullPage: true });
console.log(截图保存到 ${output});
await browser.close();
})();
crawl.js — 多页爬虫
// 使用方法:node crawl.js <选择器> [最大页数]
const puppeteer = require('puppeteer');
const url = process.argv[2];
const selector = process.argv[3];
const maxPages = parseInt(process.argv[4]) || 10;
if (!url || !selector) {
console.error('使用方法:node crawl.js <选择器> [最大页数]');
process.exit(1);
}
(async () => {
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
let allData = [];
for (let i = 1; i <= maxPages; i++) {
const pageUrl = url.includes('?') ? ${url}&page=${i} : ${url}?page=${i};
console.error(爬取:${pageUrl});
await page.goto(pageUrl, { waitUntil: 'networkidle2' });
const data = await page.$$eval(selector, els => els.map(el => el.textContent.trim()) );
if (data.length === 0) break;
allData.push(...data);
}
console.log(JSON.stringify(allData, null, 2));
await browser.close();
})();