使用JavaScript或Puppeteer

时间:2019-05-08 15:05:48

标签: javascript jquery html puppeteer

我正在构建一个框架,该框架将对基础结构上托管的网站进行爬网,以验证没有违反我们政策的内容。如果有禁止的内容,我们将在其他详细信息中对其进行截图。

很明显,如果元素由于位于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年前的事情,从那以后发生了很大变化,我也可以使用伪造者,在他的情况下是不可能的)。

4 个答案:

答案 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)
        });
      }