puppeteer / node.js - 进入页面,点击加载更多直到所有评论加载,将页面保存为mhtml
Posted
技术标签:
【中文标题】puppeteer / node.js - 进入页面,点击加载更多直到所有评论加载,将页面保存为mhtml【英文标题】:puppeteer / node.js - enter page, click load more until all comments load, save page as mhtml 【发布时间】:2022-01-20 17:55:33 【问题描述】:我想要完成的是进入此站点https://www.discoverpermaculture.com/permaculture-masterclass-video-1 等到它加载,从disqus 加载所有cmets(单击“加载更多cmets”按钮直到它不再存在)并将页面保存为mhtml 以供离线使用。
我在这里Puppeteer / Node.js to click a button as long as it exists -- and when it no longer exists, commence action 发现了类似的问题,但不幸的是,由于某种原因,尝试检测“加载更多 cmets”按钮不起作用。
似乎 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();
【问题讨论】:
【参考方案1】:您只是在等待处理 ajax 请求。您可以简单地保存 cmets 的总数(DISQUS 插件的左上角)并将其与 cmets 数组进行比较,一旦数组等于总数,然后您就检索了每个 cmets。
我已经发布了一些关于等待 ajax 请求的内容,您可以在此处查看:https://***.com/a/66092889/3645650。
或者,一种更简单的方法是只使用 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
响应以检索线程号。
【讨论】:
我很确定这个 WaitForSelector 有问题。我已经编辑了我的代码(愚蠢的方法,但添加了一些控制台日志和 4 秒超时,这似乎工作正常,因为当我保存屏幕截图时,我可以看到所有 cmets 都已加载并且“加载更多 cmets”按钮可见。当我运行此代码时屏幕上打印的所有内容都是“不可见”,这看起来很奇怪。 试图通过“span.comment-count”选择器获取评论数,但也没有用。【参考方案2】:原来问题在于 disqus cmets 在 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);
修改后就完美了
【讨论】:
以上是关于puppeteer / node.js - 进入页面,点击加载更多直到所有评论加载,将页面保存为mhtml的主要内容,如果未能解决你的问题,请参考以下文章
使用Puppeteer将Node悬停在Node.js中的element和getComputedStyle上?
如何使用 puppeteer 和 Node js 为 pdf 页面生成屏幕截图
使用 Puppeteer 和 Node.JS 在网站上的 iFrame 中找不到隐藏的输入元素