Puppeteer page.click 有效,但 page.evaluate + 文档单击不起作用

avo*_*ado 4 javascript puppeteer

我看过很多帖子(例如,请参阅此处此处),说我可以通过以下代码单击某些内容,

await page.click('.route-redirect-box');   // via Puppeteer page.click

await page.evaluate((css_selector) => {
  document.querySelector(css_selector).click();  // or via page.evaluate
}, css);
Run Code Online (Sandbox Code Playgroud)

但是,正如我在某些网站上测试的那样,使用模式看起来page.click总是有效,但page.evaluate实际上无效headless: false

比如这个网站页面,我尝试点击如下内容,

var css = '#searchPaginationTop > nav > a:nth-child(5)';
await page.evaluate((css_selector) => { document.querySelector(css_selector).click();}, css);
Run Code Online (Sandbox Code Playgroud)

什么也没发生,但如果我使用page.click,它会按预期工作。

我在想,我想点击的元素不是普通的可点击元素,因为该元素的 html 代码如下,

<a class="svg" data-goto-page="3" data-total-pages="3" data-ga="event" data-ga-category="Brands at allbeauty-Burberry-Pagination" data-ga-action="Brands at allbeauty-Burberry-Pagination-Next-Touch" data-ga-label="Brands at allbeauty-Burberry-Pagination-Next-Link">
    <svg viewBox="0 0 21.9 38.7" alt="Next Page" title="Next Page ">
        <use xlink:href="#icon-ab-arrow-right">
        </use>
    </svg>
</a>
Run Code Online (Sandbox Code Playgroud)

难道是因为这个元素是一些data-ga东西,所以page.evaluate不能点击它?

Tho*_*orf 6

简答

  • page.evaluate(() => document.querySelector('SELECTOR').click());只是触发click事件
  • page.click('SELECTOR') 点击时尝试模仿人类行为

解释

让我们查看这两种方法的文档以真正了解发生了什么。

page.evaluate(() => document.querySelector('SELECTOR').click());

让我们看看MDN 文档是怎么说的:

[...] 它触发元素的点击事件。

这就是它所做的一切。它只是触发click事件,以便调用所有侦听元素单击事件的处理程序。这意味着,它不关心元素是否在当前视口之外。元素甚至可能被隐藏(通过 CSS)并且click事件仍然会触发。

让我们将其与“傀儡方式”进行比较:

page.click

puppeteer 文档中关于page.click以下内容的部分:

此方法使用 获取元素selector,根据需要将其滚动到视图中,然后使用page.mouse来单击元素的中心。[...]

这意味着,木偶操纵者在这里模仿人类行为。首先,该元件被滚动到视图,则鼠标移动在元件的顶部(触发任何其他事件等mouseovermouseenter等上的方式)。最后通过模拟鼠标点击按钮(见Mousepuppeteer代码中对应的类)。这也会触发任何相关事件(如mousedown)。

当您自己触发 JavaScript 事件时,复杂的 UI 库可能不喜欢它。请记住,它们通常针对人类交互进行优化,而不是针对与机器人的交互进行优化。这意味着,UI 库可能会侦听mousedownormouseenter事件(例如),而不是直接侦听click事件。

表现得“像人”

在与未知网站互动时,最好尽量表现得像人一样。即使页面没有任何特定的“反机器人”措施,也可能使用期望特定事件流的框架。

顺便说一下,您不是唯一遇到此问题的人。查看这些问题是否有类似问题: