当人力资源部门需要快速获取市场薪酬数据时,传统手动查询方式效率低下且容易出错。我曾使用RPA工具为团队开发过自动化解决方案,但在实际应用中逐渐暴露出扩展性不足的问题。本文将分享如何通过PlayWright这一现代化浏览器自动化工具,构建更灵活、更强大的Java版薪酬数据采集系统。
在企业自动化领域,RPA工具如UiPath、来也Uibot等因其低代码特性广受欢迎。它们确实为业务人员提供了快速实现自动化的可能,但当需求变得复杂时,这些工具往往力不从心。
RPA工具的主要局限性:
相比之下,PlayWright作为微软推出的浏览器自动化库,提供了更底层的控制能力:
| 特性 | RPA工具 | PlayWright |
|---|---|---|
| 执行效率 | 中等 | 高 |
| 灵活性 | 有限 | 极高 |
| 语言支持 | 专有语言 | 多语言支持 |
| 调试能力 | 基础 | 专业级 |
| 维护成本 | 随时间增加 | 相对稳定 |
java复制// PlayWright基础初始化示例
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch(
new BrowserType.LaunchOptions().setHeadless(false));
BrowserContext context = browser.newContext();
Page page = context.newPage();
// 后续操作...
}
使用Maven构建Java项目时,需添加PlayWright依赖:
xml复制<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.32.0</version>
</dependency>
提示:建议同时安装PlayWright的浏览器二进制文件,可通过
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install"命令完成
为防止被目标网站识别为自动化脚本,需要配置一些反检测措施:
java复制page.addInitScript("Object.defineProperties(navigator, {"
+ "webdriver:{get:()=>undefined},"
+ "plugins:{get:()=>[1,2,3]},"
+ "languages:{get:()=>['zh-CN','zh']}"
+ "});");
// 设置合理的用户代理
page.setExtraHTTPHeaders(Map.of(
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
));
常见反检测技巧:
实现Boss直聘的搜索功能需要模拟以下步骤:
java复制String keyword = "Java高级工程师";
page.navigate("https://www.zhipin.com/");
// 等待搜索框可见并输入关键词
page.locator("input[name='query']").waitFor();
page.locator("input[name='query']").fill(keyword);
// 点击搜索按钮并等待响应
Response response = page.waitForResponse(
r -> r.url().contains("/wapi/zpgeek/search/joblist.json"),
() -> page.locator("text='搜索'").click()
);
Boss直聘采用前后端分离架构,数据通过API接口返回。我们可以直接拦截这些请求获取结构化数据:
java复制if (response.ok()) {
JSONObject json = new JSONObject(response.text());
JSONArray jobList = json.getJSONObject("zpData")
.getJSONArray("jobList");
// 数据处理逻辑
processJobData(jobList);
}
关键数据字段解析:
jobName: 职位名称salaryDesc: 薪资描述brandName: 公司名称jobLabels: 职位标签workAddr: 工作地点实现完整的数据采集需要考虑分页逻辑:
java复制// 获取总页数
int totalPages = json.getJSONObject("zpData")
.getInt("totalPages");
for (int i = 2; i <= totalPages; i++) {
String pageUrl = String.format(
"https://www.zhipin.com/wapi/zpgeek/search/joblist.json?page=%d", i);
Response pageResponse = page.waitForResponse(
r -> r.url().equals(pageUrl),
() -> page.evaluate("fetch('" + pageUrl + "')")
);
// 处理每页数据...
}
注意:实际应用中应添加适当的延迟和错误处理,避免请求过于频繁导致IP被封禁
使用Apache POI库将采集到的数据导出为Excel:
java复制void exportToExcel(List<JobData> jobs, String filePath) throws IOException {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("职位数据");
// 创建表头
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("职位名称");
headerRow.createCell(1).setCellValue("公司名称");
// 其他列...
// 填充数据
for (int i = 0; i < jobs.size(); i++) {
Row row = sheet.createRow(i + 1);
JobData job = jobs.get(i);
row.createCell(0).setCellValue(job.getJobName());
// 其他字段...
}
FileOutputStream fos = new FileOutputStream(filePath);
workbook.write(fos);
workbook.close();
}
将采集的数据进行简单统计分析,可生成以下洞察:
java复制// 示例:计算平均薪资
double avgSalary = jobs.stream()
.mapToDouble(JobData::getSalaryMid)
.average()
.orElse(0);
请求优化策略:
java复制// 禁用图片加载提升性能
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setIgnoreHTTPSErrors(true)
.setJavaScriptEnabled(true)
.setViewportSize(null)
.setExtraHTTPHeaders(Map.of(
"Accept", "text/html,application/xhtml+xml",
"Accept-Language", "zh-CN,zh;q=0.9"
)));
健壮的系统需要完善的错误处理:
java复制try {
// 主要业务逻辑
} catch (PlaywrightException e) {
// 浏览器操作异常处理
logger.error("PlayWright操作失败: " + e.getMessage());
// 重试或恢复逻辑...
} catch (JSONException e) {
// 数据解析异常
logger.error("JSON解析错误: " + e.getMessage());
} finally {
// 资源清理
if (page != null) page.close();
}
结合Spring Scheduler实现定时采集:
java复制@Scheduled(cron = "0 0 9 * * MON-FRI") // 工作日早上9点执行
public void scheduledJobDataCollection() {
try (Playwright playwright = Playwright.create()) {
// 采集逻辑...
}
}
在实际项目中,这套系统帮助HR团队将市场调研效率提升了80%,数据准确性达到95%以上。最关键的是,当业务需求变化时,基于代码的解决方案可以快速调整适应,这是RPA工具难以比拟的优势。