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

如何在Puppeteer中定位Poshmark的分页‘下一页’按钮?

问题:Poshmark爬虫分页按钮定位及函数调用故障
  • 开发爬取Poshmark男装夹克页面卖家用户名的程序,目标遍历所有页面提取数据,但所有分页按钮HTML类名完全一致,无法区分「下一页」按钮
  • 普通Chrome浏览器中页面为无限滚动模式,因此编写了scrollToBottom异步函数,但Puppeteer启动的Chrome显示分页按钮,导致无限滚动逻辑失效
  • gotoNextPage函数无法正确找到并点击目标按钮
  • initItemArea函数未被有效调用,相关逻辑已硬编码到main函数中

目标页面:https://poshmark.com/category/Men-Jackets_&_Coats?sort_by=like_count&all_size=true&my_size=false

相关代码:

const e = require('express');
const puppeteer = require('puppeteer');
const url = "https://poshmark.com/category/Men-Jackets_&_Coats?sort_by=like_count&all_size=true&my_size=false";
let usernames = [];

 const initItemArea = async (page) => {

    const itemArea = await page.evaluate(() => {
        return Array.from(document.querySelectorAll('.tc--g.m--l--1.ellipses')).map(x => x.textContent);
    });
 }

 const pushToArray =  async (itemArea, page) => {

    itemArea.forEach(function (element) {
        //console.log('username: ', $(element).text());
        usernames.push(element);
    });

 };

 const scrollToBottom = async (itemArea, page) => {

    while (true) {

        previousHeight = await page.evaluate('document.body.scrollHeight');
        await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
        await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
    
        await new Promise((resolve) => setTimeout(resolve, 1000));

        await page.screenshot({path : "ss.png"})
    }
};


const gotoNextPage = async (page) => {
    await page.waitForSelector(".button.btn.btn--pagination");

    const nextButton = await page.evaluate((page) => {
        document.querySelector(".button.btn.btn--pagination")
    });
    
    await page.click(nextButton);
    console.log('Next Page Loading')

};


async function main() {
 
    const client = await puppeteer.launch({
        headless: false,
        executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
    });

    const page = await client.newPage();
    await page.goto(url);
    await page.waitForSelector(".tc--g.m--l--1.ellipses");

    const itemArea = await page.evaluate(() => {
        return Array.from(document.querySelectorAll('.tc--g.m--l--1.ellipses')).map(x => x.textContent);
    });


    gotoNextPage(page)
    
};

main();

解决方案

1. 正确定位「下一页」按钮

分页按钮类名相同,但可通过文本内容或aria-label属性区分「下一页」。Poshmark的下一页按钮包含「Next」文本,可使用精准选择器:

const gotoNextPage = async (page) => {
  try {
    // 等待下一页按钮出现,超时5秒避免无后续页面时卡住
    const nextButton = await page.waitForSelector('.button.btn.btn--pagination:has-text("Next")', { timeout: 5000 });
    await nextButton.click();
    // 等待页面加载完成,以商品元素出现为标志
    await page.waitForSelector(".tc--g.m--l--1.ellipses");
    console.log('已跳转到下一页');
    return true; // 返回true表示跳转成功
  } catch (err) {
    console.log('已无更多页面');
    return false; // 返回false表示无后续页面
  }
};

注意:page.evaluate无法直接返回DOM元素到Puppeteer上下文,直接通过Puppeteer的选择器API操作即可。

2. 修复函数调用与逻辑整合

  • 改造initItemArea使其返回提取的用户名数组,简化pushToArray为同步数组操作:
const initItemArea = async (page) => {
  return await page.evaluate(() => {
    // 去除用户名前后空格,避免无效数据
    return Array.from(document.querySelectorAll('.tc--g.m--l--1.ellipses')).map(x => x.textContent.trim());
  });
};

const pushToArray = (itemArea) => {
  // 用扩展运算符批量添加,提升效率
  usernames.push(...itemArea);
};
  • 在main函数中循环调用分页与提取逻辑,处理异步操作(必须加await):
async function main() {
  // 修正变量名:client改为browser更符合Puppeteer惯例
  const browser = await puppeteer.launch({
    headless: false,
    executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
  });

  const page = await browser.newPage();
  // 等待网络空闲,确保页面完全加载
  await page.goto(url, { waitUntil: 'networkidle2' });

  let hasNextPage = true;
  while (hasNextPage) {
    // 提取当前页用户名
    const itemArea = await initItemArea(page);
    pushToArray(itemArea);
    console.log(`当前页提取${itemArea.length}个用户名,累计${usernames.length}个`);
    // 尝试跳转到下一页
    hasNextPage = await gotoNextPage(page);
  }

  // 输出结果或保存到文件
  console.log('所有用户名提取完成:', usernames);
  await browser.close();
};

main();

3. 其他优化

  • 删除无用的express依赖,代码未用到该包
  • 移除无效的scrollToBottom函数,适配Puppeteer的分页模式
  • 添加错误捕获,避免单个页面加载失败导致程序崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:25:37