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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:09:19