MCP实战分享:使用Playwright MCP+Claude进行高效数据采集
- AIGC
- 4天前
- 35热度
- 0评论
如何选择最适合自己的MCP资源库?
面对这么多资源,如何选择最适合自己的呢?我根据实际经验给出以下建议:
根据技术水平选择:
- 零基础用户:推荐Fleur(Mac用户)或mcp.run(Web用户)
- 入门级开发者:Smithery.ai或Aimcp.info(中文用户)是理想选择
- 专业开发者:MCP官方仓库和MCP-Toolkit提供更多技术深度
根据使用场景选择:
- Cursor用户:首选Cursor Directory
- VS Code用户:MCP Marketplace是最佳选择
- 需要网页自动化:直接使用Playwright MCP Server
- GitHub工作流优化:GitHub-MCP能大幅提升效率
- 多模型测试需求:Glama MCP提供了理想的测试环境
根据特定需求选择:
- 寻找最全面的资源:mcp.so目前收录量最大
- 需要精选高质量工具:Awesome MCP Servers质量更有保障
- 追踪最新动态:PulseMCP的周更新是了解前沿的窗口
- 需要中文支持:Aimcp.info为中文用户提供便利
实战分享:使用Playwright MCP+Claude进行高效数据采集
在我的日常工作中,MCP已经成为提升效率的关键工具。以下是1个实际案例:使用Playwright MCP进行数据采集。
项目背景挑战
在一个市场分析项目中,我需要从15个不同的电商网站采集产品数据,包括:
- 产品名称
- 价格信息
- 品牌
- 规格参数
- 用户评分
- 库存状态
传统方法是手动访问每个网站,将数据复制到Excel表格,然后进行格式清洗和数据标准化,整个过程耗时约3天,且容易出错。如何提高效率成为了关键挑战。
解决方案概述
我采用的方案核心是将Playwright MCP作为Claude的"眼睛和手",实现对网页的自动化操作与数据提取。整体流程包括:
- 搭建Playwright MCP服务环境
- 在Claude中连接MCP服务
- 为Claude提供数据采集任务指南
- 利用Claude执行网页导航与数据提取
- 数据清洗与标准化处理
- 导出为标准格式
详细实施步骤
步骤1:配置Playwright MCP环境
首先,我们需要在本地安装并启动Playwright MCP服务:
# 安装Playwright MCP
npm install -g @playwright/mcp
# 启动MCP服务器
npx playwright-mcp start --port 8080
优化技巧:为了提高稳定性,特别是对付一些加载缓慢的电商网站,我使用了以下启动配置:
npx playwright-mcp start --port 8080 --timeout 120000 --headless=false
这将超时时间延长至120秒,并使用有头模式便于调试过程中观察浏览器行为。
步骤2:在Claude中连接MCP服务
根据使用的Claude客户端,连接方式略有不同:
Claude桌面应用:
- 打开Claude桌面应用
- 在右上角点击设置图标
- 选择"高级"选项卡
- 添加MCP配置:
- 名称:
playwright
- URL:
http://localhost:8080
- 名称:
- 点击连接按钮
Cursor编辑器:arduino
/mcp connect playwright http://localhost:8080
连接成功后,Claude会显示确认信息,表明它已经可以使用浏览器功能了。
步骤3:为Claude创建数据采集任务指南
与Claude交流的提示词设计至关重要。以下是我实际使用的任务指南模板:markdown
我需要从以下电商网站采集产品数据:
[网站URL列表]
对每个网站,请获取以下信息:
- 产品名称
- 价格
- 品牌
- 规格/尺寸
- 用户评分(如有)
- 库存状态
工作流程:
1. 访问网站并分析页面结构
2. 处理可能的弹窗(Cookie通知、登录提示等)
3. 定位产品列表元素
4. 提取每个产品的详细信息
5. 将数据整理为标准格式
6. 导出为CSV格式
请使用Playwright MCP执行这些任务,并实时报告进度。对于每个网站的特殊情况,我会提供额外指导。
步骤4:Claude执行数据采集
当Claude接收到任务后,它会使用Playwright MCP进行以下操作:
1.初始化浏览器并访问目标网站php
// 启动浏览器
const browser = await playwright.chromium.launch({
headless: false,
slowMo: 50 // 稍微放慢操作,避免被反爬
});
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
viewport: { width: 1280, height: 800 },
locale: 'en-US'
});
const page = await context.newPage();
await page.goto('https://example-ecommerce.com');
2.处理常见弹窗障碍
网站常见的Cookie提示、登录弹窗等会阻碍数据采集。Claude会自动处理这类情况:javascript
// 处理Cookie通知
try {
const cookieSelectors = [
'button:has-text("Accept")',
'button:has-text("Accept All")',
'button:has-text("同意")',
'[id*="cookie"] button',
'.cookie-banner button'
];
for (const selector of cookieSelectors) {
if (await page.$(selector)) {
await page.click(selector);
await page.waitForTimeout(1000);
break;
}
}
} catch (e) {
console.log("尝试处理Cookie通知,但没有找到匹配元素或出现错误");
}
3.分析页面结构并定位产品元素
Claude会分析页面DOM结构,找出最合适的选择器:ini
// 分析产品列表结构
const productContainers = [
'.product-grid .product-item',
'.products-list .item',
'[data-testid="product-card"]',
'.search-result-items .product-tile'
];
let productSelector;
for (const selector of productContainers) {
const count = await page.$
$eval(selector, items => items.length);
if (count > 0) {
productSelector = selector;
console.log(`找到产品列表: $
{selector},共${count}个商品`);
break;
}
}
4.提取产品数据
确定选择器后,Claude会提取每个产品的详细信息:dart
// 提取产品信息
const products = await page.$$eval(productSelector, items => {
return items.map(item => {
// 尝试多种可能的选择器组合以提高适应性
const findText = (selectors) => {
for (const selector of selectors) {
const element = item.querySelector(selector);
if (element && element.textContent.trim()) {
return element.textContent.trim();
}
}
return 'N/A';
};
return {
name: findText(['.product-name', '.title', 'h2', 'h3']),
price: findText(['.price', '.product-price', '[data-price]']),
brand: findText(['.brand', '.product-brand', '[data-brand]']),
specs: findText(['.specs', '.details', '.description']),
rating: findText(['.rating', '.stars', '[data-rating]']),
stock: findText(['.stock', '.availability', '.inventory'])
};
});
});
5.翻页处理
对于多页数据,Claude会实现翻页逻辑:ini
// 翻页逻辑
let hasNextPage = true;
let currentPage = 1;
const maxPages = 5; // 限制页数,避免过长时间运行
while (hasNextPage && currentPage < maxPages) {
console.log(
正在处理第${currentPage}页
);
// 提取当前页数据...
// 检查是否有下一页
const nextPageSelectors = [
'a.next',
'.pagination .next',
'button:has-text("Next")',
'[aria-label="Next page"]'
];
let foundNextButton = false;
for (const selector of nextPageSelectors) {
const nextButton = await page.$(selector);
if (nextButton) {
foundNextButton = true;
await nextButton.click();
await page.waitForSelector(productSelector); // 等待新页面加载
await page.waitForTimeout(2000); // 等待页面稳定
break;
}
}
if (!foundNextButton) {
hasNextPage = false;
}
currentPage++;
}
步骤5:数据清洗与标准化
原始采集的数据通常需要进一步处理,Claude会执行以下数据清洗操作:ini
// 数据清洗与标准化
const processedProducts = products.map(product => {
// 清理价格格式,提取数值
const cleanPrice = product.price.replace(/[^\d.,]/g, '')
.replace(/,/g, '.');
const numericPrice = parseFloat(cleanPrice);
// 规范化评分 (通常从文本转为1-5的数值)
let normalizedRating = 'N/A';
if (product.rating !== 'N/A') {
const ratingMatch = product.rating.match(/(\d+(.\d+)?)/);
if (ratingMatch) {
normalizedRating = parseFloat(ratingMatch[1]);
// 如果是10分制,转换为5分制
if (normalizedRating > 5) {
normalizedRating = (normalizedRating / 2).toFixed(1);
}
}
}
// 规范化库存状态
let stockStatus;
const stockText = product.stock.toLowerCase();
if (stockText.includes('in stock') || stockText.includes('有货')) {
stockStatus = '有货';
} else if (stockText.includes('out of stock') || stockText.includes('无货')) {
stockStatus = '无货';
} else {
stockStatus = '未知';
}
return {
name: product.name,
price: isNaN(numericPrice) ? product.price : numericPrice,
brand: product.brand,
specs: product.specs,
rating: normalizedRating,
stock: stockStatus
};
});
步骤6:导出为CSV格式
最后,Claude会将处理好的数据导出为CSV格式:kotlin
// 转换为CSV
const createCSV = (data) => {
if (!data || data.length === 0) return '';
const headers = Object.keys(data[0]);
const rows = [
headers.join(','), // 表头行
...data.map(item =>
headers.map(key => {
// 处理包含逗号的文本,用引号包围
const val = String(item[key] || '');
return val.includes(',') ?
"${val}"
: val;
}).join(',')
)
];
return rows.join('\n');
};
const csv = createCSV(processedProducts);
console.log(csv);
关键优化技巧
在实践中,我发现以下几个优化点能显著提高成功率:
1.模拟真实用户行为
网站的反爬机制越来越先进,模拟真实用户行为是关键:javascript
// 模拟真实用户行为
const simulateHumanBehavior = async (page) => {
// 随机滚动
await page.evaluate(() => {
window.scrollBy({
top: 100 + Math.random() * 400,
behavior: 'smooth'
});
});
// 随机暂停
await page.waitForTimeout(1000 + Math.random() * 2000);
// 偶尔悬停在某个元素上
const randomElements = await page.$$('a, button, img');
if (randomElements.length > 0) {
const randomIndex = Math.floor(Math.random() * randomElements.length);
await randomElements[randomIndex].hover();
}
};
// 在页面操作中定期调用
await simulateHumanBehavior(page);
2.错误恢复与重试机制
网页采集经常会遇到临时性错误,加入重试机制很重要:javascript
// 带重试的元素操作
const clickWithRetry = async (page, selector, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
await page.click(selector);
return true;
} catch (err) {
console.log(
点击元素失败(尝试 ${attempt}/${maxRetries}): ${err.message}
);
if (attempt === maxRetries) return false;
await page.waitForTimeout(1000);
}
}
return false;
};
3.并行处理多个网站
为了进一步提高效率,我实现了多个网站的并行处理:ini
// 并行处理多个网站(控制并发数)
const scrapeMultipleSites = async (urls, maxConcurrent = 3) => {
const results = {};
const chunks = [];
// 将URL列表分成多个小批次
for (let i = 0; i < urls.length; i += maxConcurrent) {
chunks.push(urls.slice(i, i + maxConcurrent));
}
// 按批次并行处理
for (const chunk of chunks) {
console.log(
开始处理新的批次: ${chunk.join(', ')}
);
const promises = chunk.map(url => scrapeWebsite(url));
const batchResults = await Promise.all(promises);
// 合并结果
chunk.forEach((url, index) => {
results[url] = batchResults[index];
});
}
return results;
};
4.应对动态加载内容
现代电商网站大多使用动态加载,需要特别处理:ini
// 处理动态加载内容
const waitForDynamicContent = async (page, itemSelector, timeout = 10000) => {
const startTime = Date.now();
let prevCount = 0;
while (Date.now() - startTime < timeout) {
// 检查元素数量
const currentCount = await page.$$eval(itemSelector, items => items.length);
// 如果元素数量不再增加,说明加载完成
if (currentCount > 0 && currentCount === prevCount) {
console.log(
动态内容已加载完成,找到${currentCount}个元素
);
return true;
}
prevCount = currentCount;
// 滚动以触发加载
await page.evaluate(() => {
window.scrollBy(0, 500);
});
await page.waitForTimeout(500);
}
console.log(
等待动态内容超时,已找到${prevCount}个元素
);
return prevCount > 0;
};
成果
通过实施这套方案,我们取得了显著成效:
- 时间效率: 从手动操作的3天缩短到自动化的4小时,效率提升约18倍
- 数据准确性: 错误率从25%降至2%,准确率提升了23%
- 数据完整性: 自动化采集能够处理更多数据点,提供了更全面的分析基础
- 可扩展性: 方案可轻松扩展到更多网站,只需微调适配各网站特性
Playwright MCP + Claude的组合极大地简化了网页数据采集工作,让AI成为数据处理的强大助手。这种方式不仅提高了效率,还降低了错误率,是企业数字化转型的理想工具。
随着MCP技术的不断发展,未来我们可以期待更多创新应用场景。例如,将这套系统与数据分析和可视化工具结合,实现从数据采集到分析报告的全流程自动化。
总结
MCP技术的出现,极大地拓展了AI大模型的能力边界,让Claude、Cursor等工具真正成为开发者的得力助手。这14个MCP资源库为不同需求的用户提供了丰富的工具选择,大大降低了使用门槛。