Puppeteer实践-节省时间的利器

前言

看网上大多提到Puppeteer都是用它来做自动化测试,爬虫等等,而我在看到这个工具的第一想法是,它能否帮我提高开发过程中使用工具的效率。

在我的工作环境中,线上服务查慢接口,看日志等等需要首先登录jumpserver,再一步步寻址找到我需要的工具,点开它,选择自己需要的服务查看日志,查看耗时等等,这个过程鼠标点击好多次,重复工作很多,我就想能否节省前面这些步骤的时间。

直接给出效果吧

以上效果除了登录时候需要输入下验证码,之后没有移动鼠标,都有代码自行完成,包括自动打开树状结构菜单,自动选择skywalking,自动在打开的界面点击确认,自动选择最近7天,自动选择我要选择的项目,自动切换模式。

当你平时工作中看个东西有一堆固定的前置操作的时候,就可以想到,是否可以用它节省你的时间

执行代码

import puppeteer from 'puppeteer';

(async () => {
    // Launch the browser and open a new blank page
    const browser = await puppeteer.launch({
        headless: false,
        defaultViewport: null,
        args: ['--start-maximized']
    });
    const context = browser.defaultBrowserContext();

    // 要查看哪个项目的skywalking
    let project = 'project-center';

    // 设置默认权限
    context.overridePermissions('https://jumpserver.xxx.com.cn/luna/', ['clipboard-read']);
    
    const page = await browser.newPage();

    await page.goto('https://jumpserver.xxx.com.cn/core/auth/login/?next=/luna/');
   
    // await page.mouse.click(1389,383);

    await page.waitForSelector('#id_username')
    
    // 替换为用户名和密码输入框的选择器
    await page.type('#id_username', '真实用户名');
    await page.type('#password', '真实密码');

    const captchaClassExists = await page.$('.captcha')
    if(captchaClassExists){
        await page.waitForSelector('#AssetTree_3_a');
    }else{
        await page.click('#login-form > div:nth-child(6) > button')
    }

    await new Promise(r => setTimeout(r, 1000));
    const [elementHandle] = await page.$x('//*[@id="AssetTree_3"]');
    if (elementHandle) {
        await elementHandle.click();
    }

    await new Promise(r => setTimeout(r, 500));
    await page.waitForSelector('#AssetTree_5')
    await page.click('#AssetTree_5')

    await new Promise(r => setTimeout(r, 500));
    await page.waitForSelector('#AssetTree_7')
    await page.click('#AssetTree_7')

    await new Promise(r => setTimeout(r, 500));
    await page.waitForSelector('#AssetTree_12')
    await page.click('#AssetTree_12')

    await page.waitForSelector('#mat-dialog-0 > elements-asset-tree-dialog > div > div.dialog-body.mat-dialog-content > mat-dialog-actions > button')
    await page.click('#mat-dialog-0 > elements-asset-tree-dialog > div > div.dialog-body.mat-dialog-content > mat-dialog-actions > button')
    
    await new Promise(r => setTimeout(r, 10000));

    // 确认60分钟警告
    await placeMarker(page, 1148, 450);
    await page.mouse.click(1148, 450);

    // 选择最近7天
    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 1244, 102);
    await page.mouse.click(1244, 102);

    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 913, 288);
    await page.mouse.click(913, 288);

    // 选择trace
    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 795, 226);
    await page.mouse.click(795, 226);
    // 选择输入框
    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 639, 280);
    await page.mouse.click(639, 280);

    // 输入具体的项目名
    await new Promise(r => setTimeout(r, 100));
    await page.keyboard.type(project)

    // 选择具体的项目
    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 639, 332);
    await page.mouse.click(639, 332);

    // 选择Duration
    await new Promise(r => setTimeout(r, 1000));
    await placeMarker(page, 816, 381);
    await page.mouse.click(816, 381);

    await new Promise(r => setTimeout(r, 200));
    await placeMarker(page, 816, 463);
    await page.mouse.click(816, 463);
})();
let enableMarkerPlacement = false;
// 封装的放置标记的函数
async function placeMarker(page, x, y) {
    if (enableMarkerPlacement) {
        await page.evaluate(({ x, y }) => {
            const marker = document.createElement('div');
            marker.style.width = '10px';
            marker.style.height = '10px';
            marker.style.background = 'red';
            marker.style.position = 'absolute';
            marker.style.top = `${y}px`;
            marker.style.left = `${x}px`;
            marker.style.zIndex = '10000';
            marker.style.borderRadius = '50%';
            document.body.appendChild(marker);
        }, { x, y });
    }
}

因为jumpserver点击具体工具后的界面是canvas,没有界面元素,所以只能按位置进行点击,所以这个代码在不同的电脑可能还运行不了相同的效果。但其提供了一种思路,其它人要模仿,这里唯一的问题点是如何获取我在界面上要点击的座标?
关于这点,做前端的应该比较熟,我这里提供一种方法,直接打开浏览器,按F12,打开console标签,里面输入

document.addEventListener('mousemove', (event) => {
    console.log(`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);
});

接下来你鼠标移动到哪里,console都会显示当前鼠标的座标,这样你就可以估算canvas你要点击的按钮的座标位置了。

在写代码期间可以把enableMarkerPlacement参数改为true,它会显示模拟点击的座标位置,画个小红点,不至于摸不着头脑不知道自己是否真的点击了
抛砖引玉,各位大神给出你们的离谱用法吧~