【问题标题】:How Can I Check if Google Recaptcha V2 Puzzle is Displayed?如何检查是否显示 Google Recaptcha V2 拼图?
【发布时间】:2026-01-29 10:20:04
【问题描述】:

当 Recaptcha 显示拼图而不是复选框时,我正在尝试调整容器 div 的大小。这通常发生在单击复选框后。我该怎么做?

我知道某些条件会强制 Recaptcha V2 显示拼图而不是复选框。然而,Api 不会返回表明此更改已发生的属性或事件。有没有一种方法可以在 JavaScript 中或通过 API 来识别 Recaptcha V2 是否正在显示拼图?

注意:这是我没有在 API url 中指定 fallback=true 的情况。

【问题讨论】:

  • 它会在 iframe 中打开 Recaptcha 吗?您是否能够检查页面上是否存在具有这些类的内容?
  • 他们将 HTML 添加到您的页面。您需要轮询您的页面并查找此类名称g-recaptcha-bubble-arrow - 查找突变可能会有所帮助:*.com/questions/3219758/…
  • 它确实在 iframe 中打开。我查看了一些元素及其生成的 id,但我没有运气使用 DOM 操作来定位这些 css 选择器
  • 由于您无法访问 iframe 中的元素,我认为最好的办法是在您认为应该调用 iframe 之前和之后检查 iframe 的大小。但是,由于您正在尝试确定它是拼图还是复选框,因此您编写的任何代码都将非常脆弱。
  • 我觉得 API 在决定渲染拼图而不是复选框时应该提供一些属性或钩子。我不知道我的这个想法是否完全正确!

标签: javascript jquery captcha recaptcha


【解决方案1】:

很遗憾,Google 没有 API 事件来跟踪这一点,但我们可以使用 Mutation Observer Web API 自行跟踪 Google API 的 DOM 更改。 浏览器很好地支持它:

首先,我们需要创建一个目标元素,用于观察 Google iframe 的外观。我们将目标 document.body 作为 iframe 将附加到它:

const targetElement = document.body;

然后我们需要为 MutationObserver 创建一个配置对象。在这里,我们可以指定我们将在 DOM 更改中跟踪的确切内容。请注意,默认情况下所有值都是“false”,因此我们只能留下“childList”——这意味着我们将只观察目标元素的子节点变化——在我们的例子中是 document.body:

const observerConfig = {
    childList: true,
    attributes: false,
    attributeOldValue: false,
    characterData: false,
    characterDataOldValue: false,
    subtree: false
};

然后我们需要创建一个函数,当观察者检测到我们在配置对象中指定的特定类型的 DOM 更改时将调用该函数。第一个参数表示Mutation Observer 对象的数组

function DOMChangeCallbackFunction(mutationRecords) {
    mutationRecords.forEach((mutationRecord) => {
        if (mutationRecord.addedNodes.length) { //check only when notes were added to DOM
            var reCaptchaParentContainer = mutationRecord.addedNodes[0];
            var reCaptchaIframe = reCaptchaParentContainer.querySelectorAll('iframe[title*="recaptcha"]');

            if (reCaptchaIframe.length) { // Google reCaptcha iframe was loaded
                console.log('Yay!');
                reCaptchaObserver.disconnect(); // We don't want to observe more DOM changes for better performance
                // Challenge was loaded -- DO SOMETHING HERE
            }
        }
    });
}

差不多了。剩下的唯一事情——实例化一个观察者本身并开始观察 DOM 变化:

const reCaptchaObserver = new MutationObserver(DOMChangeCallbackFunction);
reCaptchaObserver.observe(targetElement, observerConfig);

希望对你有帮助:)

【讨论】:

    【解决方案2】:

    您可以使用setInterval 执行此操作。如果用户从不选中该框,这可能会杀死浏览器。您可能希望延迟运行此程序,直到他们开始填写表单或等到他们将鼠标悬停/关注 reCaptcha 元素。您可能还需要一个更具体的选择器(通过将您的 recaptcha 包装在一个 div 中)以防您有其他 iframe 可以在代码中使用相同的标题。使用 cmets 中提到的 mutationObserver 是一个更好的主意。 希望这能满足您的需求。

    function isPuzzleDisplayed (selector) {
      /**
       * @param {string} selector
       * @returns boolean - if the specified element exists
       */
        return document.querySelectorAll(selector).length >= 1;
    }
    
    var timer = setInterval(function () {
      /**
       * Check if element exists every 0 seconds.
       * If it does, kill timer, else keep running forever!
       * WARNING! This is not performant.
       */
        if (isPuzzleDisplayed('iframe[title*="recaptcha challenge"]')) {
            console.log('But this is how you do it!');
            /* run your code here */
            clearInterval(timer);
            timer = 0;
        } else {
            console.log('It is true the Api however does not return a property or event that would indicate that this change has happened. >', timer);
        }
    }, 0);

    【讨论】: