Puppeteer 在当前页面或 iFrame 中查找元素
Posted
技术标签:
【中文标题】Puppeteer 在当前页面或 iFrame 中查找元素【英文标题】:Puppeter find element in current page OR iFrame 【发布时间】:2021-09-02 05:13:24 【问题描述】:我的页面中有一些元素有时在 iFrame 中,有时则不在。 在这两种情况下,它们具有相同的 id 来识别它们。
在 page 或 iFrame 中找到它们的最佳且快速的方法是什么?
我目前使用的代码在元素位于 iFrame 中时有效,但如果元素仅在页面中则无效。 我以为mainFrame会是iFrame之外的“currentPage”,但似乎代码搜索只在iFrame中,而不是在外面。
async function recursiveFindInFrames(inputFrame, selector)
const frames = inputFrame.childFrames();
const results = await Promise.all(
frames.map(async frame =>
const el = await frame.$(selector);
if (el) return el;
if (frame.childFrames().length > 0)
return await recursiveFindInFrames(frame, selector);
return null;
)
);
return results.find(Boolean);
async function findInFrames(page, selector)
const result = await recursiveFindInFrames(page.mainFrame(), selector);
if (!result)
console.log('The selector ',selector,' could not be found in any child frames.')
return result;
...
//Element that could be in an iFrame, or not
const element = await findInFrames(page2, 'input[name="myField"]');
await element.click();
...
【问题讨论】:
【参考方案1】:当任何元素在同一个页面中时,它肯定会更容易找到,而且您不需要特殊的功能来做到这一点。
如果您知道元素的 id,这就足够了:$('#element_id')
(如果元素的 id 没有硬编码,您也可以使用变量)。
【讨论】:
【参考方案2】:您不能添加page.evaluate
和querySelector
吗?
async function findInFrames(page, selector)
const framesResult = await recursiveFindInFrames(page.mainFrame(), selector);
if (!framesResult)
console.log('The selector ',selector,' could not be found in any child frames.')
const pageResult = await page.evaluate(() => document.querySelector(selector))
return framesResult || pageResult || null;
【讨论】:
【参考方案3】:使用frames
方法代替childFrames
。
所以这段代码
const frames = inputFrame.childFrames();
应该这样写:
const frames = inputFrame.frames();
frames 方法也以数组的形式返回 MainFrame。因此,该函数也会在 mainFrame 上进行搜索。
【讨论】:
【参考方案4】:要检查除嵌套子框架之外的主页,您可以在遍历子框架之前先检查inputFrame
。它可能看起来像这样:
async function recursiveFindInFrames(inputFrame, selector)
var el = await inputFrame.$(selector);
if (el)
return el;
const childFrames = inputFrame.childFrames();
for (let i = 0; i < childFrames.length; i++)
el = await recursiveFindInFrames(childFrames[i], selector);
if (el)
return el;
return null;
async function findInFrames(page, selector)
const result = await recursiveFindInFrames(page.mainFrame(), selector);
if (!result)
console.log('The selector, ' + selector + ', could not be found in any child frames.')
return result;
...
//Element that could be in an iFrame, or not
const element = await findInFrames(page2, 'input[name="myField"]');
if (element)
await element.click();
...
请注意,此方法按顺序搜索,等待每一帧的结果。如果你想并行搜索子框架,你可以这样做:
async function recursiveFindInFrames(inputFrame, selector)
var el = await inputFrame.$(selector);
if (el)
return el;
const childFrames = inputFrame.childFrames();
const elementPromises = childFrames.map(frame => recursiveFindInFrames(frame, selector));
for (let i = 0; i < elementPromises.length; i++)
el = await elementPromises[i];
if (el)
return el;
return null;
也就是说,我认为潜在的改进非常小。
【讨论】:
以上是关于Puppeteer 在当前页面或 iFrame 中查找元素的主要内容,如果未能解决你的问题,请参考以下文章