Nodejs puppeteer 模拟点击无限循环的问题。

发布于 1周前 作者 sinazl 来自 nodejs/Nestjs

Nodejs puppeteer 模拟点击无限循环的问题。

代码如下,功能是抓取 jandan 段子区的段子吐槽。由于段子的吐槽是分页的,会有个“点击加载更多”的按钮,要判断该按钮是否存在,存在则持续点击。遇到的问题是,要判断按钮是否存在,要用到 document 对象,但 document 对象只存在于page.evaluate()内;而如果放在page.evaluate()里判断按钮是否存在,存在则点击,点击要用到page.click(selector),而page对象是又不存在于page.evaluate()里,该怎么处理?

PS: 案例用了 jandan,如果冒犯到站长或者蛋友,还请包涵,只是测试不做他用。

const puppeteer = require('puppeteer');
const chalk = require('chalk');

(async() => { const browser = await puppeteer.launch({ executablePath: ‘/Applications/Chromium.app/Contents/MacOS/Chromium’, headless: true, slowMo: 200, ignoreHTTPSErrors: true, timeout: 10000 }); console.log(chalk.green(‘服务正常启动’)); try { const page = await browser.newPage(); page.on(‘console’, msg => { if (typeof msg === ‘object’) { console.dir(msg); } else { console.log(chalk.blue(msg)); } });

    // 进入页面
    await page.goto('https://jandan.net/duan/page-94#comments');
    const commentBtn = '.tucao-btn';
    await page.click(commentBtn);

    const tucao = '.jandan-tucao';
    const tucao_hot = '.tucao-hot';
    const tucao_list = '.tucao-list';
    const tucao_more = 'div.jandan-tucao-more:not([style])';
    await page.waitForSelector(tucao);
    

    const cmts = await page.evaluate( (selector, more) => {

        const tucaos = Array.from(document.querySelector(selector).querySelectorAll('.tucao-row'));
        return tucaos.map(comment => {
            const author = comment.querySelector('.tucao-author').textContent;
            const content = comment.querySelector('.tucao-content').textContent.trim();
            const oo = comment.querySelector('.tucao-oo').textContent;
            const xx = comment.querySelector('.tucao-xx').textContent;
            return `${author} oo[${oo}] xx[${xx}]: \n${content}\n`;
        });
    }, tucao_list, tucao_more);

    console.log(cmts.join('\n'));

    await browser.close();
    console.log(chalk.green('服务正常结束'));
} catch (error) {
    console.log(error);
    console.log(chalk.red('服务意外终止'));
    await browser.close();
} finally {
    process.exit(0);
}

})();


4 回复

<br>while ( document.querySelector(tucao_more) )<br>{<br> page.click(tucao_more);<br> page.waitFor(1000);<br>}<br>
就是这段代码放哪里的问题


await page.goto(‘https://jandan.net/duan/page-94#comments’, {
timeout: 10000,
waitUntil: ‘domcontentloaded’,
});
const commentBtn = ‘.tucao-btn’;
let length = await page.evaluate(commentBtn => {
let btns = document.querySelectorAll(commentBtn);
btns.forEach(el => el.click());
return btns.length;
}, commentBtn);
console.log(length);

你这是对每一条段子都点击吐槽按钮,和我帖子里的需求不是一回事啊。我是点击第一个吐槽按钮,如果吐槽条数很多会分页,希望把加载更多都点过后再解析。

在Node.js中使用Puppeteer进行模拟点击并实现无限循环,需要注意几个方面,包括页面加载、元素选择、点击事件的触发以及循环控制。以下是一个简单的示例代码,演示如何使用Puppeteer实现模拟点击的无限循环:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({headless: false}); // 非headless模式方便观察
    const page = await browser.newPage();
    await page.goto('https://example.com'); // 替换为目标网站

    const clickElementSelector = '#someButton'; // 替换为目标按钮的选择器

    async function clickElement() {
        await page.waitForSelector(clickElementSelector); // 等待元素加载
        await page.click(clickElementSelector); // 点击元素
    }

    // 使用setInterval实现无限循环点击
    const clickInterval = setInterval(clickElement, 3000); // 每3秒点击一次

    // 可选:设置超时以停止循环(例如,运行10分钟后停止)
    setTimeout(() => {
        clearInterval(clickInterval);
        browser.close();
    }, 10 * 60 * 1000);

})().catch(err => console.error(err));

注意事项

  1. 确保选择器正确无误,以避免因找不到元素而导致的错误。
  2. headless: false 设置为非headless模式,方便观察浏览器操作,但在生产环境中建议设置为 true 以提高效率。
  3. 使用 setInterval 实现循环点击,并通过 setTimeout 设置超时以避免无限循环(可选)。

根据实际需求调整选择器、URL、点击间隔及超时时间。

回到顶部