【Puppeteer 实战】自动登录后台并分页提取表格数据(含 50 条/页切换)

本文通过一个完整示例,演示如何使用 Puppeteer 自动访问后台系统、设置 Cookie、切换分页大小,并循环点击「下一页」抓取所有表格 HTML 数据。


一、应用场景说明

在实际项目中,我们经常遇到以下需求:

  • 后台系统需要登录才能访问
  • 数据列表有分页,需要自动翻页
  • 希望批量抓取每一页的表格数据
  • 页面基于 Element UI(el-pagerbtn-next

本文将一步步实现:

✅ 打开后台页面

✅ 使用 Cookie 模拟登录

✅ 切换为 50 条/页

✅ 自动计算总页数

✅ 循环点击「下一页」

✅ 抓取所有表格 HTML


二、环境准备

1. 安装 Puppeteer

bash 复制代码
npm install puppeteer

2. Node.js 版本

建议使用:

  • Node.js ≥ 14
  • Puppeteer ≥ 19

三、完整示例代码

下面是完整可运行的示例代码:

js 复制代码
const puppeteer = require('puppeteer');
const fs = require('fs');

// 封装一个延时方法
function waitForTimeout(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false // 关闭无头模式,方便调试
  });

  try {
    const page = await browser.newPage();
    await page.setViewport({ width: 1920, height: 800 });

    // 1. 进入后台登录页面
    await page.goto('http://localhost:8093/admin');

    // 2. 设置登录 Cookie(模拟已登录)
    const cookies = [
      {
        name: 'Admin-Token',
        value: '你的 token',
        domain: 'localhost',
        path: '/'
      }
    ];

    // 如果需要启用 Cookie,取消注释
    // await page.setCookie(...cookies);

    // 3. 跳转到数据列表页
    await page.goto('http://localhost:8093/category');

    // 4. 切换分页大小为 50 条/页
    const pageSizeXPath = '//span[text()="50条/页"]';
    await page.waitForXPath(pageSizeXPath);
    const [pageSizeBtn] = await page.$x(pageSizeXPath);

    if (pageSizeBtn) {
      await pageSizeBtn.evaluate(el => el.click());
      console.log('已切换为 50 条/页');
    }

    // 5. 获取总页数
    await page.waitForSelector('ul.el-pager');
    const liElements = await page.$$('ul.el-pager li');
    const lastLi = liElements[liElements.length - 1];

    let totalPages = 1;
    if (lastLi) {
      totalPages = parseInt(
        await page.evaluate(li => li.textContent, lastLi)
      );
      console.log('总页数:', totalPages);
    }

    // 6. 循环点击下一页并抓取表格
    const tableSelector = 'table';
    const nextBtnSelector = 'button.btn-next';

    await page.waitForSelector(nextBtnSelector, { visible: true });

    let currentPage = 1;
    let allTableHTML = '';

    while (currentPage <= totalPages) {
      console.log(`正在抓取第 ${currentPage} 页`);

      // 抓取当前页表格
      const tables = await page.$$(tableSelector);
      for (const table of tables) {
        const html = await table.evaluate(el => el.outerHTML);
        allTableHTML += html + '\n\n';
      }

      // 点击下一页
      const nextBtn = await page.$(nextBtnSelector);
      if (!nextBtn) break;

      await nextBtn.click();
      await waitForTimeout(3000);
      currentPage++;
    }

    console.log('分页抓取完成');

    // 7. 可选:保存为 HTML 文件
    fs.writeFileSync('tables.html', allTableHTML, 'utf-8');

    console.log('表格 HTML 已保存到 tables.html');

    // await browser.close();
  } catch (e) {
    console.error('发生错误:', e);
  }
})();

四、关键代码讲解

1️⃣ 模拟登录(Cookie)

js 复制代码
await page.setCookie({
  name: 'Admin-Token',
  value: 'xxx',
  domain: 'localhost',
  path: '/'
});

适用于:

  • 后台 token 登录
  • 无需输入账号密码
  • 常见于 Vue / Element UI 项目

2️⃣ XPath 精准点击「50条/页」

js 复制代码
const xpath = '//span[text()="50条/页"]';
const [el] = await page.$x(xpath);
await el.evaluate(e => e.click());

优点:

  • 不依赖 class
  • 文本唯一即可定位

3️⃣ 获取 Element UI 总页数

js 复制代码
ul.el-pager li:last-child

Element UI 的分页结构非常规整,最后一个 li 就是最大页数。


4️⃣ 自动翻页核心逻辑

js 复制代码
while (currentPage <= totalPages) {
  await nextBtn.click();
  await waitForTimeout(3000);
}

建议:

  • 使用显式等待
  • 避免点击过快导致请求丢失
相关推荐
不叫猫先生24 天前
Puppeteer + BrightData代理集成实战,解锁高效Web数据采集新范式
爬虫·数据采集·puppeteer
vivo互联网技术1 个月前
数字人动画云端渲染方案
前端·ffmpeg·puppeteer·web3d
卤代烃1 个月前
🤝 了解 CDP (Chrome DevTools Protocol):browser-use 背后的隐藏功臣
前端·chrome·puppeteer
qq_420362033 个月前
PDF导出服务
前端·pdf·状态模式·node·puppeteer
是晓晓吖4 个月前
Puppeteer page.on('response',fn)的最佳实践之等待响应
前端·puppeteer
是晓晓吖4 个月前
说说 page.on('response',fn)
前端·puppeteer
北漂大橙子4 个月前
运营妹子复制 200 个 URL 手酸到哭,我用 Puppeteer 写了个工具,1 小时搞定!
前端·puppeteer
是晓晓吖4 个月前
Page.waitForResponse的竞态条件与最佳实践
前端·puppeteer