Puppeteer基础入门--表单交互与截图

表单交互与截图

课程目标

  • 🎯 掌握表单元素的自动化操作
  • 🎯 实现页面截图与PDF生成
  • 🎯 完成模拟登录+数据抓取综合案例
  • 🎯 理解浏览器环境隔离机制

一、表单操作核心API

1.1 基础输入操作

// 文本输入(支持模拟输入速度)
await page.type('#username', 'admin', { delay: 100 })

// 清空输入框
await page.$eval('#search', el => el.value = '')
// 或
await page.focus('#search')
await page.keyboard.down('Control')
await page.keyboard.press('A')
await page.keyboard.up('Control')
await page.keyboard.press('Backspace')

// 单选框/复选框
await page.click('#remember-me')

1.2 高级表单组件

// 文件上传(需暴露input元素)
const input = await page.$('input[type="file"]')
await input.uploadFile('./avatar.png')

// 下拉选择(两种方式)
// 方式1:直接修改value
await page.select('#country', 'CN')
// 方式2:模拟点击选择
await page.click('#country option[value="US"]')

// 日期选择器
await page.evaluate(() => {
  document.querySelector('#birthday').value = '2023-07-20'
})

二、截图与PDF生成

2.1 页面截图

// 基础截图
await page.screenshot({
  path: 'screenshot.png',
  fullPage: true,    // 截取完整页面
  quality: 70,       // 图片质量(0-100)
  omitBackground: true, // 透明背景
  clip: {            // 指定区域
    x: 0,
    y: 0,
    width: 800,
    height: 600
  }
})

// 元素截图
const element = await page.$('#chart-container')
await element.screenshot({
  path: 'chart.png',
  padding: 10 // 增加边距
})

2.2 PDF生成

await page.pdf({
  path: 'report.pdf',
  format: 'A4',             // 纸张尺寸
  margin: {
    top: '20mm',
    right: '20mm',
    bottom: '20mm',
    left: '20mm'
  },
  printBackground: true,    // 包含背景
  displayHeaderFooter: true,// 显示页眉页脚
  headerTemplate: '<div style="font-size:10px">Page <span class="pageNumber"></span></div>',
  footerTemplate: '<div style="font-size:10px">Generated by Puppeteer</div>'
})


三、综合实战:baidu模拟登录

3.1 完整实现代码

const puppeteer = require('puppeteer');
const fs = require('fs');

(async () => {
    const browser = await puppeteer.launch({
        headless: false, // 显示浏览器窗口
        executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', // 指定Chrome路径
        args: ['--no-sandbox', '--disable-setuid-sandbox'], // 添加沙箱模式禁用选项
        env: { NODE_ENV: 'production' }, // 指定环境变量
    });
    const page = await browser.newPage();

    try {
        // 设置浏览器视口
        await page.setViewport({ width: 1440, height: 900 });

        // 导航到登录页
        await page.goto('https://www.baidu.com/', {
            waitUntil: 'networkidle2',
            timeout: 15000,
        });

        // 等待登录按钮
        await page.waitForSelector('#s-top-loginbtn');
        // 点击登录按钮
        await page.$eval('#s-top-loginbtn', (btn) => btn.click());

        await page.waitForSelector('#TANGRAM__PSP_11__userName');
        // 输入凭据
        await page.type('#TANGRAM__PSP_11__userName', 'your_username', { delay: 50 });
        await page.type('#TANGRAM__PSP_11__password', 'your_password', { delay: 50 });
        await page.$eval('#TANGRAM__PSP_11__isAgree', (btn) => btn.click());

        // 提交表单
        await Promise.all([page.waitForNavigation(), page.click('#TANGRAM__PSP_11__submit')]);

        // 验证登录成功
        await page.$eval('.avatar-user', { timeout: 5000 });

        // 保存登录后截图
        await page.screenshot({
            path: 'github-profile.png',
            fullPage: true,
        });

        // // 提取用户信息
        // const userInfo = await page.evaluate(() => ({
        //     name: document.querySelector('.vcard-names').innerText.trim(),
        //     bio: document.querySelector('.user-profile-bio').innerText,
        //     repos: document.querySelectorAll('[itemprop="repositories"]').length,
        // }));
        // console.log('登录成功:', userInfo);

        // 生成PDF报告
        await page.pdf({
            path: 'github-profile.pdf',
            format: 'A4',
        });
    } catch (err) {
        await page.screenshot({ path: 'error.png' });
        console.error('登录失败:', err);
    } finally {
        await browser.close();
    }
})();

3.2 关键技术点

  1. 混合等待策略networkidle2 + 元素显式等待
  2. 并行操作Promise.all处理导航跳转
  3. 输入模拟delay参数实现拟人输入
  4. 多格式输出:同时保存PNG和PDF

四、常见问题解决方案

4.1 表单提交失败

// 方案1:强制提交(当按钮不可点击时)
await page.$eval('form', form => form.submit())

// 方案2:触发验证事件
await page.evaluate(() => {
  document.querySelector('#email').dispatchEvent(new Event('blur'))
})

4.2 截图异常处理

// 处理弹窗干扰
page.on('dialog', async dialog => {
  await dialog.dismiss();
});

// 处理懒加载内容
await autoScroll(page);

async function autoScroll(page) {
  await page.evaluate(async () => {
    await new Promise(resolve => {
      let totalHeight = 0;
      const distance = 100;
      const timer = setInterval(() => {
        const scrollHeight = document.body.scrollHeight;
        window.scrollBy(0, distance);
        totalHeight += distance;
        if (totalHeight >= scrollHeight) {
          clearInterval(timer);
          resolve();
        }
      }, 100);
    });
  });
}

五、课后作业

5.1 基础任务

  1. 实现知乎登录自动化并保存个人主页截图
  2. 抓取天气查询网站数据生成PDF日报
  3. 添加截图失败的重试机制

5.2 进阶挑战

  1. 实现滑块验证码绕过(使用移动模拟)
  2. 开发自动生成网页缩略图工具
  3. 为PDF添加自定义水印

🛠️ 推荐工具:

  • 截图优化:sharp
  • PDF处理:pdf-lib
  • 验证码识别:tesseract.js

下节课预告:异步控制与事件监听 - 掌握浏览器事件监听与流程控制 ⚙️

配套资源

  1. GitHub登录案例完整代码
  2. Puppeteer截图官方文档
  3. PDF生成参数详解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Penk是个码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值