puppeteer / node.js - 进入页面,点击加载更多直到加载所有评论,将页面保存为 mhtml

puppeteer / node.js - enter page, click load more until all comments load, save page as mhtml

我想要完成的是进入这个网站 https://www.discoverpermaculture.com/permaculture-masterclass-video-1 等待它加载,从 disqus 加载所有评论(单击 'Load more comments' 按钮直到它不再存在)并将页面保存为 mhtml供离线使用。

我在这里发现了类似的问题 但不幸的是,由于某种原因,尝试检测“加载更多评论”按钮不起作用。

似乎 WaitForSelector('a.load-more__button') 没有工作,因为它打印出来的所有内容都是“不可见的”。

这是我的代码

const puppeteer = require('puppeteer');
const url = "https://www.discoverpermaculture.com/permaculture-masterclass-video-1";

const isElementVisible = async (page, cssSelector) => {
    let visible = true;
    await page
        .waitForSelector(cssSelector, { visible: true, timeout: 4000 })
        .catch(() => {
            console.log('not visible');
            visible = false;
        });
    return visible;
};

async function run () {

    let browser = await puppeteer.launch({
        headless: true,
        defaultViewport: null,
        args: [
            '--window-size=1920,10000',
        ],
    });
    const page = await browser.newPage();
    const fs = require('fs');
    await page.goto(url);
    await page.waitForNavigation();
    await page.waitForTimeout(4000)

    const selectorForLoadMoreButton = 'a.load-more__button';
    let loadMoreVisible = await isElementVisible(page, selectorForLoadMoreButton);
    while (loadMoreVisible) {
        console.log('load more visible');
        await page
            .click(selectorForLoadMoreButton)
            .catch(() => {});
    await page.waitForTimeout(4000);

        loadMoreVisible = await isElementVisible(page, selectorForLoadMoreButton);
    }

    const cdp = await page.target().createCDPSession();
    const { data } = await cdp.send('Page.captureSnapshot', { format: 'mhtml' });
    fs.writeFileSync('page.mhtml', data);
    browser.close();
}
run();

您正在等待处理 ajax 请求。您可以简单地保存评论总数(DISQUS 插件的左上角)并将其与评论数组进行比较,一旦数组等于总数,那么您就检索了每条评论。

我在等待 ajax 请求时发布了一些东西,您可以在这里看到它:.


或者,更简单的方法是只使用 DISQUS api。

评论是公开的。您可以只使用网站上的 api 密钥:

https://disqus.com/api/3.0/threads/listPostsThreaded?limit=50&thread=7187962034&forum=pdc2018&order=popular&cursor=1%3A0%3A0&api_key=E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F

parameter options
limit Default to 50. Maximum is 100.
thread Thread number. eg: 7187962034.
forum Forum id. eg: pdc2018.
order desc, asc, popular.
cursor Probably the page number. Format is 1:0:0. eg: Page 2 would be 2:0:0.
api_key The platform api key. Here the api key is E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F.

如果您必须遍历不同的页面,您需要拦截 xhr 响应以检索线程号。

原来问题是 disqus 评论在 iframe 中

//needed to add those 2 lines
const elementHandle = await page.waitForSelector('iframe');
const frame = await elementHandle.contentFrame();

//and change 'page' to 'frame' below
let loadMoreVisible = await isElementVisible(frame, selectorForLoadMoreButton);
while (loadMoreVisible) {
    console.log('load more visible');
    await frame
        .click(selectorForLoadMoreButton)
        .catch(() => {});
    await frame.waitForTimeout(4000);
    loadMoreVisible = await isElementVisible(frame, selectorForLoadMoreButton);
}

此更改后效果完美