PhantomJS无法点击现有元素。

5
我在Windows 8.1上使用PhantomJS 1.9.7,我想在输入用户名和密码后单击登录按钮。我可以输入用户名和密码,但是当我想让PhantomJS点击该按钮时,它能够找到该元素但无法点击。根据以前的帖子,我发现需要创建事件并使用"dispatchEvent"。我这样做了,但我收到以下错误:

TypeError:'undefined'不是函数(评估'elm.dispatchEvent(event)')

我还尝试从EventListener获得帮助,但对此也出现了相同的错误。

如何单击一个元素?

var page = require('webpage').create();

page.open('URL', function() {
    var submitButton = enterUserAndPassAndLogin();      
    click(submitButton);
    phantom.exit();
});

function enterUserAndPassAndLogin() {
    var element = page.evaluate(function()  {
        document.querySelector('input[name="username"]').value = "*******";
        document.querySelector('input[name="password"]').value = "*******";
        return document.getElementsByTagName("Button");
    });
    return element;
}

function click(elm) {
    var event = document.createEvent("MouseEvent");
    event.initMouseEvent("click", true, true, window,
        0, 0, 0, 0, 0, false, false, false, false, 0, null);
    elm.dispatchEvent(event);
}

你能否写出你正在使用的点击按钮的代码? - Steven de Salas
@cracker:请不要使用行内代码跨度来突出单词——这通常是不必要的,如果确实需要强调某些内容,请使用粗体或斜体。行内代码跨度(顾名思义)仅用于句子中的代码:在编辑帖子时请记住这一点。 - Qantas 94 Heavy
好的,谢谢,下次我会注意的。 - cracker
我已经将我的代码添加到上面的帖子中。它有什么问题吗? - user3321210
2个回答

1
代码存在两个问题。首先,DOM元素无法从页面上下文(page.evaluate)传递到外部。对应的docs中的行:

注意:evaluate函数的参数和返回值必须是一个简单的原始对象。经验法则是:如果可以通过JSON序列化,则没有问题。

闭包、函数、DOM节点等都将不起作用!

因此,submitButton[null]。由于返回了一个数组,错误消息没有显示实际的问题。由于DOM元素无法传递到外部,单击必须在page.evaluate内部发生。
由于page.evaluate是沙盒化的,所以click函数必须在页面上下文中定义。外部的变量和函数不能直接访问。
可能的脚本是这样的:
var page = require('webpage').create();

page.open('URL', function() {
    enterUserAndPassAndLogin();
    setTimeout(function(){
        // wait a little to maybe see the click result
        phantom.exit();
    }, 1000);
});

function enterUserAndPassAndLogin() {
    page.evaluate(function()  {
        function click(elm) {
            var event = document.createEvent("MouseEvent");
            event.initMouseEvent("click", true, true, window,
                0, 0, 0, 0, 0, false, false, false, false, 0, null);
            elm.dispatchEvent(event);
        }
        document.querySelector('input[name="username"]').value = "*******";
        document.querySelector('input[name="password"]').value = "*******";
        click(document.getElementsByTagName("Button")[0]);
    });
}

-1

只需插入Jquery并执行

$(selector).trigger('click');

请注意,如果页面使用异步提交,则页面加载事件不会触发,但是它“正在加载”,您必须等待响应。
或许等待几秒钟就足以让异步提交返回。

仅仅建议“用jQuery来解决!”并不能解决原帖中所遇到的具体问题。 - Sam Hanley
亲爱的@sphanley:只是想提醒一下,海报上说:dispatchEvent未定义。Jquery有这个方法。肯定的。 - Sesertin
是的,但这就像告诉一个请求帮助启动汽车的人只是坐公交车一样。当然,jQuery可以触发元素上的点击事件,但OP正在使用PhantomJS,而不是jQuery。 - Sam Hanley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接