(操纵手)有没有办法通过x,y获取元素查询?

时间:2019-02-20 13:09:32

标签: javascript puppeteer

我想通过传递x,y坐标来获取元素查询选择器。

或者满足坐标的元素很少。

也许我可以做mouse.click(x,y)然后获得clicked元素,但是我不希望页面采取任何行动只是获取元素的查询。

有可能这样做吗?

2 个答案:

答案 0 :(得分:3)

如果只需要视口坐标中最顶层的元素,则可以尝试DocumentOrShadowRoot.elementFromPoint()。如果您需要组成一个唯一的选择器,则可以尝试从DocumentOrShadowRoot.elementsFromPoint()处理元素数组(在下面的示例中添加更多检查-类,id,属性,子级计数和顺序等):

'use strict';

const puppeteer = require('puppeteer');

(async function main() {
  try {
    const browser = await puppeteer.launch();
    const [page] = await browser.pages();

    await page.goto('https://example.org/');

    console.log(await page.evaluate(() => {
      return document.elementFromPoint(100, 100).tagName;
    }));

    console.log(await page.evaluate(() => {
      return document.elementsFromPoint(100, 100)
                     .map(({ tagName }) => tagName).reverse().join(' > ');
    }));

    await browser.close();
  } catch (err) {
    console.error(err);
  }
})();
DIV
HTML > BODY > DIV

答案 1 :(得分:1)

首先必须考虑到,您可能会在同一位置获得许多元素,包括主HTML元素。

首先,您需要获取所有元素:

Array.prototype.slice.call(document.getElementsByTagName("*"))

然后,我们现在每个元素都有一个名为getClientRects的函数,该函数将返回一个“盒子”数组。

基于此,我们可以过滤所需坐标中具有一个框的所有元素:

var x = 150;
var y = 1250;
Array.prototype.slice.call(document.getElementsByTagName("*")).filter(e =>
     Array.prototype.slice.call(e.getClientRects()).find(rect => 
         rect.top <= x && rect.bottom >= x && rect.left <= y && rect.right >= y))

您可以在Puppeteer的evaluate通话中执行类似的操作。