写点什么

Puppeteer 实践:复杂的问题简单化

  • 2024-05-09
    福建
  • 本文字数:2367 字

    阅读完需:约 8 分钟

Puppeteer实践:复杂的问题简单化

最近遇到一个需求需要将上千条的数据写入到基于 Wordpress 搭建的系统中,但是对于底层数据录的写入逻辑不是很清楚,通过 sql 各种写入也没有完全达到效果。

后面想了想或许可以换一个方向,不能从底层逻辑写入数据那就通过正常操作写入。由于数据量大所以需要自动化处理,这时候就想到了之前用过的Puppeteer,这个库可以模拟操作浏览器的各种行为,包括获取数据和操作提交等。对于这个场景很适合,不用管底层的实现逻辑,也不需要去扒源码了解各种加密加签的逻辑,只需要模拟操作提交数据即可。

复杂的问题瞬间简单了,在这篇文章中记录如何使用Puppeteer批量提交数量。

安装 Puppeteer

在这之前确保你已经安装了 Node.js。运行以下命令安装 Puppeteer:

npm install puppeteer
复制代码

Puppeteer 脚本

接下来编写需要执行的脚本,创建一个名为puppeteer.js的文件,并添加以下代码:

const puppeteer = require('puppeteer');
(async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('https://baidu.com'); await browser.close();})();
复制代码

puppeteer.launch() 是用于启动一个浏览器实例,为后续的网页操作和自动化测试提供基础。可以接受一些配置选项,如指定浏览器的路径、是否启用无头模式、设置视口大小等。完整配置还有很多,可查阅官网了解。

保持用户状态

需要写入的系统是需要登录后才能操作且需要多次操作,所以在操作过程中需要记录用户状态。这一点我们可以在初始化浏览器实例的时候配置 userDataDiruserDataDir 用于指定一个目录,该目录用于存储浏览器的用户数据,如缓存、Cookie、本地存储数据等。可以让 Puppeteer 在每次启动浏览器时都使用相同的用户数据,从而保持用户状态的连续性。

const browser = await puppeteer.launch({    userDataDir: 'userA' });
复制代码

模拟登录

然后就是第一次的模拟登录和后续操作校验登录状态。通过 page.cookies() 获取存储的用户数据,如果不存在则模拟登录。

// 从puppeteer中获取cookieconst cookies = await page.cookies(); let isLogin = falsecookies.forEach(json => {    if (json.name.includes('wordpress')) {        isLogin = true    }});
console.log('[ isLogin ] >', isLogin)
if (!isLogin) { // 模拟输入用户名密码 await page.type('#user_login', 'XXXX', { delay: 100 }); await page.type('#user_pass', 'XXXX', { delay: 100 }); // 模拟点击 await page.click('#rememberme', { delay: 110 }); await page.click('#wp-submit', { delay: 120 }); // 等待页面完全加载 await page.waitForNavigation() }
复制代码

数据处理

接下来就是业务数据处理了,首先将数据转换成 JSON 方便批量处理。每次处理一批数组,这里在 for 循环中使用 Promise 同步处理,待所有的数据都处理完成后关闭浏览器结束脚本。在 performAsyncOperation 中执行具体的数据操作过程。

const list = require('./list.js')
function performAsyncOperation(item) { return new Promise(async (resolve, reject) => { // todo item resolve(); });}
// 使用async函数来包裹异步操作async function processItems() { for (const item of list) { // 使用await等待异步操作完成 await performAsyncOperation(item); } console.log('All items processed'); await browser.close();}
processItems()
复制代码

这里有一点特殊处理,要写入的数据是在 iframe 中的元素,需要通过以下方式对 iframe 中的 dom 进行修改赋值。

const elementHandle = await page.waitForSelector('#content_ifr');const frame = await elementHandle.contentFrame();await frame.waitForSelector('p:nth-child(1)');const description = item.description// 在 iframe 中使用 evaluate 方法来修改元素内的 DOMawait frame.evaluate((description) => {    // 在这里可以编写 JavaScript 代码来修改 iframe 内的 DOM    document.querySelector('p:nth-child(1)').textContent = description}, description);
复制代码

更新完一条数据后进行下一条数据的写入,这里页面提交数据后界面发生了变化,需要重新回到开始的页面继续处理。回到开始的发布页面后执行成功回调继续下一条数据处理,当所有的数据处理完成则结束脚本。

// 点击发布await page.click('#publish')// 等待页面更新await page.waitForNavigation()// 点击回到发布页面await page.click('.page-title-action', { delay: 300 })// 成功回调继续下一条处理resolve();
复制代码

总结

Puppeteer 是一个强大的库,它能够让开发者以编程方式控制 Chrome 或 Chromium。这使数据获取或操作页面数据变得更加容易,特别是对于需要与 JavaScript 交互的页面。

通过上面的例子,你应该对如何使用 Puppeteer 来处理数据有了一个基本的了解。Puppeteer 的能力远不止于此,你可以创建更复杂的脚本来模拟用户登录、填写表单、获取签名数据等。

前端的世界总是在不断变化,作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。低代码也是一个值得我们深入探索的领域,让我们拭目以待,它将给前端世界带来怎样的变革。

介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

JNPF 可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量,通过图形化、可视化的界面,以拖放组件的方式,即可快速生成应用程序的产品,大幅降低了开发企业管理类软件的难度。

希望这篇文章对你有所帮助~


用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Puppeteer实践:复杂的问题简单化_伤感汤姆布利柏_InfoQ写作社区