如何通过HTML按钮onclick事件控制Puppeteer爬虫的启动与停止?
Puppeteer启停控制实现方案
后端实现
核心思路是将Puppeteer的browser实例提到路由作用域外部存储,方便停止接口调用实例的关闭方法,同时加运行状态判断避免重复启动/停止的异常。
- 首先在路由文件最外层声明全局存储变量:
const puppeteer = require('puppeteer'); // 存储Puppeteer实例 let browserInstance = null; // 标记爬虫运行状态 let isCrawling = false;
- 修改启动路由,补充状态判断和实例存储逻辑:
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}); } });
- 新增停止路由,调用实例关闭方法:
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
相关产品推荐
相关产品推荐

