通过之前的
memory功能,我们已经实现了用户的上下文记忆能力。今天,我们计划利用MCP赋予LLM调用Playwright的能力,以实现对网页岗位信息的自动化爬取。
MCP与Playwright简介
MCP(Mastra Capability Provider)是一个适配器,允许LLM调用外部工具暴露的功能,相关介绍可参考之前的文章。Playwright则是一款广受欢迎的端到端(E2E)测试工具,熟悉E2E测试的开发者应该对其不陌生。
Playwright功能概览
Playwright的主要特性包括:
- 浏览器自动化:支持模拟用户操作,如点击、输入、页面导航等。
- 动态内容处理:能够高效处理JavaScript渲染的动态网页,特别适合爬取单页应用(SPA)或复杂Web应用。
- 无头模式:支持无界面运行,资源占用低,适合服务器端任务。
- 高级功能:提供代理设置、屏幕截图、网络请求拦截、设备模拟、多页面处理等功能。
- 跨平台支持:兼容Windows、Linux和macOS。
Playwright广泛应用于Web爬虫、自动化测试和数据提取等场景,尤其在处理复杂交互或动态内容时表现出色。
配置Playwright Server
以下是通过MCP配置Playwright Server的示例代码:
import { MCPConfiguration } from "@mastra/mcp";
const mcp = new MCPConfiguration({
servers: {
playwright: {
command: "npx",
args: ["@playwright/mcp@latest", "--vision"],
},
},
});
export default mcp;
将Playwright工具集成到Agent中:
export const careerAssistant = new Agent({
...
tools: await playWrightServer.getTools(),
});
配置完成后,与职业Agent交互时,系统会自动启动浏览器窗口,执行岗位搜索任务。目前,搜索过程通过正常模式运行,便于调试。真正使用时要添加headless参数减少用户感知。
当前存在两个待解决的问题:
- 搜索岗位时常因登录验证被拦截。
- 模型直接通过工具方法处理岗位搜索意图,逻辑不够可控。
解决登录拦截问题
Cookie注入方案
为绕过登录验证,可通过以下步骤注入Cookies:
- 手动登录目标网站,获取Cookies信息(通常为字符串格式)。
- 解析Cookies字符串,转换为Playwright可用的格式:
import cookieStr from "../../cookies/boss";
export function parseCookieString(cookieStr: string): Record<string, string> {
if (!cookieStr) return {};
return cookieStr
.split(";")
.reduce((acc: Record<string, string>, pair: string) => {
const [key, value] = pair.trim().split("=");
if (key && value) {
acc[key] = decodeURIComponent(value);
}
return acc;
}, {});
}
export async function loadCookies(platform: string) {
try {
const cookieData = parseCookieString(cookieStr);
return cookieData;
} catch (error) {
console.error(`Failed to load cookies for ${platform}:`, error);
return null;
}
}
- 创建工具函数以注入Cookies:
export const injectCookies = createTool({
id: "injectCookies",
description: "为指定平台注入Cookies",
inputSchema: z.object({
platform: z.enum(["boss", "linkedin"]),
}),
execute: async ({ context: { platform }, page }) => {
try {
const cookies = await loadCookies(platform);
if (!cookies) {
throw new Error(`未找到${platform}的Cookies`);
}
await page.context().addCookies(cookies);
return {
success: true,
data: null,
message: `成功为${platform}注入Cookies`,
};
} catch (error) {
return {
success: false,
data: null,
message: `注入Cookies失败: ${error.message}`,
};
}
},
});
优化岗位筛选主逻辑
为提高筛选逻辑的可控性,可设计一个主工具,结合Playwright工具集实现岗位筛选:
- 调用
playwright_browser_navigate工具,获取页面对象(page)。 - 将页面对象传递给
injectCookies工具,完成Cookies注入。 - 使用
playwright_browser_type工具输入岗位、地点、薪资等条件,并触发搜索。 - 调用
playwright_browser_snapshot工具,获取页面快照(YAML格式)。 - 最后,由模型解析快照内容,提取关键信息,完成任务。
下期计划
- 优化输出格式,探索使用DOM模板呈现更美观的结果。
- 深入学习Workflow和RAG(Retrieval-Augmented Generation)概念:
- 通过Workflow优化岗位筛选逻辑,使其更清晰。
- 引入RAG实现岗位查询结果缓存,降低云端流量消耗。