Puppeteer爬取LinkedIn职位时无限滚动后未返回全部结果
问题根因
代码无法采集全量职位数据,核心是3个逻辑错误:
- 异步执行顺序失控:调用
scroll()时未加await,且数据采集逻辑写在滚动函数调用之前,程序不会等滚动加载的异步流程执行完毕,页面刚加载完就已经跑完了数据采集逻辑,自然只能拿到初始渲染的24-25条结果 - 配置传参错误:原代码把
waitUntil: 'networkidle0'传给了browser.newPage()方法,该配置是页面跳转的等待规则,传给新建页面方法不生效,可能导致页面初始资源都没加载完就开始后续操作 - 滚动逻辑鲁棒性不足:调用
seeMoreJobs()时未加await,也没有做按钮存在性校验,点击后未等待新内容渲染就进入下一轮高度判断,很容易提前触发终止条件,甚至因为按钮不存在直接抛错
修复后完整代码
const puppeteer = require('puppeteer'); const db = require('../db'); const Job = require('../models/job'); (async() => { try { const browser = await puppeteer.launch({ headless: false, defaultViewport: null, // args: ['--no-zygote', '--no-sandbox'] }); const url = 'https://www.linkedin.com/jobs/search?keywords=Junior%20Software%20Developer&location=Indianapolis%2C%20IN&geoId=&trk=homepage-jobseeker_jobs-search-bar_search-submit&position=1&pageNum=0'; // 打开页面 const page = await browser.newPage(); console.log(`Navigating to ${url}`); await page.goto(url, {waitUntil: 'networkidle0'}); let lastHeight = 0; // 循环滚动加载全量职位内容 while (true) { // 滚动到当前页面底部 await page.evaluate('window.scrollTo(0, document.body.scrollHeight)'); await page.waitForTimeout(2000); // 检测"See More Jobs"按钮是否存在,存在则点击加载更多 const seeMoreBtn = await page.$('button[data-tracking-control-name="infinite-scroller_show-more"]'); if (seeMoreBtn) { await seeMoreBtn.click(); await page.waitForTimeout(2000); // 等待新内容渲染完成 } // 比对页面高度,高度无变化说明已加载到最底部 const currentHeight = await page.evaluate('document.body.scrollHeight'); if (currentHeight === lastHeight) { console.log('Done scrolling!'); break; } lastHeight = currentHeight; } // 所有内容加载完成后再采集DOM数据 const data = await page.evaluate(() => { const allJobsArr = Array.from(document.querySelectorAll('a[data-tracking-control-name="public_jobs_jserp-result_search-card"]')); return allJobsArr.map(job => { return { name: job.innerText, url: job.href, path: job.pathname } }); }); console.log(`共采集到${data.length}条职位数据`); console.log(data); // 后续数据库入库、浏览器关闭等操作可在此处添加 } catch (err) { console.log('爬取过程出错:', err); } })();
关键调整点
- 梳理全链路异步逻辑:所有异步操作(页面跳转、滚动、按钮点击、等待渲染)全部添加
await,保证执行顺序符合预期,不会出现流程提前跑完的问题 - 调整数据采集位置:将DOM提取逻辑移到滚动加载全流程结束之后,确保所有通过无限滚动加载的职位条目都已经渲染到DOM中再做提取
- 修正参数传递:将页面加载等待配置正确传给
page.goto()方法,保证初始页面资源加载完成再执行后续操作 - 优化滚动加载判断:每次滚动后先检测"See More Jobs"按钮是否存在,存在则点击并等待新内容渲染,再比对页面高度,连续两次高度无变化才判定加载到最底部,避免提前终止
- 增加异常容错:按钮点击前先做存在性检测,避免按钮未渲染时直接执行点击逻辑抛出异常打断流程
内容的提问来源于stack exchange,提问作者NickPurry
相关产品推荐
相关产品推荐

