You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过HTML按钮onclick事件控制Puppeteer爬虫的启动与停止?

Puppeteer启停控制实现方案

后端实现

核心思路是将Puppeteer的browser实例提到路由作用域外部存储,方便停止接口调用实例的关闭方法,同时加运行状态判断避免重复启动/停止的异常。

  1. 首先在路由文件最外层声明全局存储变量:
const puppeteer = require('puppeteer');
// 存储Puppeteer实例
let browserInstance = null;
// 标记爬虫运行状态
let isCrawling = false;
  1. 修改启动路由,补充状态判断和实例存储逻辑:
router.get('/settings/start', async function(req, res) {
  // 避免重复启动
  if (isCrawling || browserInstance) {
    return res.send({code: 1, msg: '爬虫已在运行中,请勿重复启动'});
  }
  const targetUrl = "https://www.google.co.th";
  try {
    browserInstance = await puppeteer.launch({headless: false, args: ["--no-sandbox"]});
    isCrawling = true;
    // 此处编写你的爬虫逻辑
    const page = await browserInstance.newPage();
    await page.goto(targetUrl);
    // 其余爬虫逻辑...

    // 监听实例断开事件,自动重置状态
    browserInstance.on('disconnected', () => {
      browserInstance = null;
      isCrawling = false;
    });
    res.send({code: 0, msg: '爬虫启动成功'});
  } catch (err) {
    // 启动失败重置状态
    browserInstance = null;
    isCrawling = false;
    res.status(500).send({code: 2, msg: '爬虫启动失败', error: err.message});
  }
});
  1. 新增停止路由,调用实例关闭方法:
router.get('/settings/stop', async function(req, res) {
  if (!browserInstance || !isCrawling) {
    return res.send({code: 1, msg: '当前没有运行中的爬虫'});
  }
  try {
    await browserInstance.close();
    browserInstance = null;
    isCrawling = false;
    res.send({code: 0, msg: '爬虫已停止'});
  } catch (err) {
    res.status(500).send({code: 2, msg: '爬虫停止失败', error: err.message});
  }
});

前端实现

原来的按钮点击跳转页面的体验较差,改为异步请求实现无刷新控制,修改后的代码如下:

<input class="form-check-input" type="checkbox" id="startswitch">
<script>
const startSwitch = document.getElementById('startswitch');
startSwitch.addEventListener('change', async function() {
  try {
    if (this.checked) {
      // 选中时调用启动接口
      const res = await fetch('/settings/start');
      const data = await res.json();
      if (data.code !== 0) {
        alert(data.msg);
        // 启动失败回滚按钮状态
        this.checked = false;
      }
    } else {
      // 取消选中时调用停止接口
      const res = await fetch('/settings/stop');
      const data = await res.json();
      if (data.code !== 0) {
        alert(data.msg);
        // 停止失败回滚按钮状态
        this.checked = true;
      }
    }
  } catch (err) {
    alert('请求失败:' + err.message);
    this.checked = !this.checked;
  }
});
</script>

注意事项

  • 如果爬虫是长时间循环执行的逻辑,建议额外新增全局运行标识,每次循环前判断标识状态,状态为false时主动跳出循环再关闭实例,避免强制关闭导致的资源泄漏
  • 以上方案为单实例爬虫实现,仅支持同一时间运行一个爬虫任务,若需要多用户独立控制,需要将browser实例和用户标识绑定存储(如session、redis),避免操作互相干扰
  • 可根据业务需求替换示例中的alert弹窗,改为页面内的状态提示提升体验

内容的提问来源于stack exchange,提问作者Boost

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:39:02