我正在构建一个框架,该框架将对基础结构上托管的网站进行爬网,以验证没有违反我们政策的内容。如果有禁止的内容,我们将在其他详细信息中对其进行截图。
很明显,如果元素由于位于overflow: hidden
父级中或位于其上方的绝对元素而不可见,则无法截屏。
2019年是否有办法知道人眼是否可以看到某个元素?
由于它位于Puppeteer内部,因此我可以使用本机Puppeteer API或所需的任何JavaScript库,因为我可以将其注入页面。
问题示例:
$('#above').html(`You can see green: ${$('#below').is(':visible')}. But can you really?`)
#above {
width: 600px;
height: 600px;
position: absolute;
background-color: red;
text-align: center;
font-size: 30px;
padding: 30px;
}
#below {
width: 440;
height: 200;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="above"></div>
<div id="below"></div>
(是的,我看到有人问这个question,但是那是7年前的事情,从那以后发生了很大变化,我也可以使用伪造者,在他的情况下是不可能的)。
答案 0 :(得分:0)
我从没有做过,但是如果元素不可见或“悬停”,则hover函数将失败。您可以执行以下操作:
let error = null;
await page.hover('yourSelector').catch(e => error = e);
if (!error) {
//The element should be visible here.
}
答案 1 :(得分:0)
我找到了一种方法(感谢 @hardkoded 将这个想法植入我的脑袋...)
我没有在所有极端情况下进行测试,但似乎可以在我的示例中使用。
基本上,我要为mouseover
事件添加一个事件监听器,该事件监听器设置一个布尔标志,然后调用操纵up的hover
函数,将鼠标移动到元素的中心。
如果设置了该标志,则该元素可见。
await page.goto('c:/temp/code.html')
const el = await page.$('#below')
await page.evaluate(el => {
el.addEventListener('mouseover', function () {
this.setAttribute('mouseover-worked', 'true')
console.log('hovered!!!')
})
}, el)
await el.hover()
const hovering_works = await page.evaluate(el => el.getAttribute('mouseover-worked'), el)
console.log(hovering_works)
如果有人发现瑕疵,请告诉我...
答案 2 :(得分:0)
在puppeteer库中内置了一种简单的方法来进行检查。您可以为page.waitForSelector
函数提供{ visible: false }
选项,该选项将检查或实际上等到元素可见:
const element = await page.waitForSelector('#selector', { visible: true });
这将做一个体面的检查。请参见函数here的完整代码。它将检查以下内容:
style.visibility !== 'hidden'
元素是否未隐藏(window.getComputedStyle
)?height
,元素width
/ top
/ bottom
/ 0
是否大于element.getBoundingClientRect()
?后一种情况也将覆盖您的示例代码,因为#below
元素的高度应为0
。因此,这是一个不错的检查,但是您将始终能够构造其中代码不起作用的情况。如果您想涵盖更多的极端情况,则还可以扩展木偶开发人员的方法。
完整代码示例
由于如果元素不存在,该函数将无法解析,因此您必须使用一个小助手Promise来使检查超时:
const element = await Promise.race([
new Promise(resolve => setTimeout(() => resolve(), 200)), // resolves without value after 200ms
page.waitForSelector('#selector', { visible: true })
]);
if (element) {
// element is visible
}
答案 3 :(得分:0)
也许您可以使用elementHandle.boundingBox()
它将返回一个Promise,它显示元素的边框(相对于主框架);如果元素不可见,则返回null。
代码段示例:
const loadMoreButton = await getDataPage.$(
'button.ao-tour-reviews__load-more-cta.js-ao-tour-reviews__load-more-cta'
);
const buttonVisible = await loadMoreButton.boundingBox();
if (buttonVisible) {
await loadMoreButton.click().catch((e) => {
console.log('???: ' + e)
});
}