You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tampermonkey设置input值后无法提交表单,如何模拟用户输入触发验证?

解决Human Benchmark数字记忆测试脚本自动提交问题

问题描述

我用Tampermonkey写脚本给Human Benchmark的数字记忆测试作弊,已经能提取需要记忆的数字,用inputElement.value = answerString把答案填入输入框,但必须手动在输入框里改一个字符才能提交,直接提交表单会导致页面重置——网站应该是用JS处理提交逻辑的。想找纯JS的方法,不用手动操作就能让网站认可输入并完成提交。

我的脚本代码(记忆阶段按Enter生效):

// ==UserScript==
// @name         Human Benchmark Cheat
// @namespace    http://tampermonkey.net/
// @version      2024-02-04
// @description  This script helps cheat on the Number Memory test on Human Benchmark by automatically entering the number you need to remember.
// @author       Caleb
// @match        https://humanbenchmark.com/tests/number-memory
// @icon         https://humanbenchmark.com/favicon.ico
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Listen for keypress events on the page
    let numberToRemember = '';
    document.addEventListener('keypress', function(event) {
        // If the Enter key is pressed, start the cheat
        if (event.key === 'Enter') {
            startCheat();
        }
    });

    // Click the button to start the test
    function pressButton() {
        // Find and click the button
        const button = document.querySelector('.css-de05nr.e19owgy710');
        button.click();
    }

    // Extracts and stores the number to remember
    function saveNumber() {
        // Find the element displaying the number
        var elements = document.querySelectorAll('.big-number');
        // Combine the text content of these elements into a single string
        numberToRemember = Array.from(elements).map(function(element) {
            return element.textContent;
        }).join('');
        // Log the number to the console for reference
        console.log(numberToRemember);
    }

    //  Put the remembered number into the input field
    function typeString() {
        // Find the input field
        var inputElement = document.querySelector('input');
        // Set the value of the input field to the remembered number
        inputElement.value = numberToRemember;
    }

    // Starts the cheat
    function startCheat() {
        // Define the class name of the element to monitor
        const className = 'number-timer-bar';

        // Find the element with the specified class name
        const elementWithClass = document.querySelector(`.${className}`);

        // Create an observer to detect when the number appears or disappears
        const observer = new IntersectionObserver(entries => {
            // Check if the element with the specified class is visible
            if (entries[0].isIntersecting) {
                // The number is visible, save it
                console.log(`Element with class '${className}' is visible!`);
                saveNumber();
            } else {
                // The number is not visible, paste the answer and submit
                console.log(`Element with class '${className}' is not visible!`);
                typeString();
                pressButton();
            }
        });

        // Start observing the element with the specified class name
        observer.observe(elementWithClass);
    }
})();

解决方案

问题核心是:直接设置input.value不会触发网站监听的用户输入事件,网站靠这些事件判断输入是否有效。另外提交时要确保网站的JS逻辑能识别输入已完成。

1. 触发输入框的用户输入事件

修改typeString函数,设置值后手动触发input和change事件,模拟真实输入:

function typeString() {
    const inputElement = document.querySelector('input');
    if (!inputElement) return;
    
    inputElement.value = numberToRemember;
    // 触发input事件(网站常用这个监听输入变化)
    inputElement.dispatchEvent(new Event('input', { bubbles: true }));
    // 触发change事件,确保表单状态更新
    inputElement.dispatchEvent(new Event('change', { bubbles: true }));
}

2. 调整提交时机

输入事件需要一点延迟才能被网站处理,可在调用typeString后加短延迟再点击按钮:

// 在startCheat的else分支里修改
else {
    console.log(`Element with class '${className}' is not visible!`);
    typeString();
    // 延迟100ms再提交,给网站时间处理输入事件
    setTimeout(pressButton, 100);
}

3. 备选:模拟按键输入(更贴近真实操作)

如果上面的方法无效,可以逐个字符模拟按键输入,完全模拟用户打字:

function typeString() {
    const inputElement = document.querySelector('input');
    if (!inputElement) return;
    
    inputElement.focus(); // 先聚焦输入框
    inputElement.value = ''; // 清空原有内容
    
    // 逐个字符触发输入事件
    for (let i = 0; i < numberToRemember.length; i++) {
        const char = numberToRemember[i];
        setTimeout(() => {
            inputElement.value += char;
            inputElement.dispatchEvent(new Event('input', { bubbles: true }));
            // 可选:模拟完整按键事件链
            inputElement.dispatchEvent(new KeyboardEvent('keydown', { key: char }));
            inputElement.dispatchEvent(new KeyboardEvent('keypress', { key: char }));
            inputElement.dispatchEvent(new KeyboardEvent('keyup', { key: char }));
        }, 50 * i); // 每个字符间隔50ms,更像真实打字
    }
    
    // 所有字符输入完成后再提交
    setTimeout(pressButton, 50 * numberToRemember.length);
}

修改后的完整脚本

// ==UserScript==
// @name         Human Benchmark Cheat
// @namespace    http://tampermonkey.net/
// @version      2024-02-04
// @description  自动完成Human Benchmark数字记忆测试
// @author       Caleb
// @match        https://humanbenchmark.com/tests/number-memory
// @icon         https://humanbenchmark.com/favicon.ico
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let numberToRemember = '';
    document.addEventListener('keypress', function(event) {
        if (event.key === 'Enter') {
            startCheat();
        }
    });

    function pressButton() {
        const button = document.querySelector('.css-de05nr.e19owgy710');
        if (button) button.click();
    }

    function saveNumber() {
        const elements = document.querySelectorAll('.big-number');
        numberToRemember = Array.from(elements).map(el => el.textContent).join('');
        console.log('记住的数字:', numberToRemember);
    }

    function typeString() {
        const inputElement = document.querySelector('input');
        if (!inputElement) return;
        
        inputElement.value = numberToRemember;
        inputElement.dispatchEvent(new Event('input', { bubbles: true }));
        inputElement.dispatchEvent(new Event('change', { bubbles: true }));
    }

    function startCheat() {
        const className = 'number-timer-bar';
        const elementWithClass = document.querySelector(`.${className}`);
        if (!elementWithClass) return;

        const observer = new IntersectionObserver(entries => {
            if (entries[0].isIntersecting) {
                console.log('数字显示中,保存数字');
                saveNumber();
            } else {
                console.log('数字已隐藏,填入答案');
                typeString();
                setTimeout(pressButton, 100);
            }
        });

        observer.observe(elementWithClass);
    }
})();

原理说明

  • 网站通常通过监听input或change事件来更新表单的有效性状态,直接设置value不会触发这些事件,所以需要手动派发。
  • 短延迟是为了给网站的JS逻辑留出处理输入的时间,避免点击提交时输入还没被识别。
  • 模拟按键输入是最接近真实用户操作的方式,几乎能绕过所有前端的输入验证逻辑。

内容的提问来源于stack exchange,提问作者Caleb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:30:10