含有PhantomJS的Selen:表格已经过验证但未提交

时间:2015-01-22 17:38:01

标签: javascript selenium web-crawler phantomjs screen-scraping

我在通过Selenium Webdriver的PhantomJS API提交表单时遇到了一个奇怪的问题。单击提交按钮后,表单将被验证(用户名和密码太短,或空白等),但最终未提交。也就是说,如果我提交无效表单并检查屏幕截图,则会有警报通知。如果我提交有效表格,则没有任何反应。页面上的JS应该验证表单,然后在单击提交按钮时提交它。

一些规则。我在提交按钮上尝试了.click().submit(),这是一个按钮元素。我还在表单本身以及Selenium允许的表单中的任意元素(如密码)上尝试.submit()

事实上,如果我驾驶Firefox而不是PhantomJS,相同的代码就可以正常运行。不过,我不想切换,因为Firefox速度较慢,而且给我带来了不可预测的连接问题。

我的规格:我在Ubuntu 14.04 LTS(GNU / Linux 3.17.1-elastic x86_64)上通过Python 2.7使用Selenium 1.43版和PhantomJS 1.98。

以下代码。首先是我的Selenium代码。然后是表单的html。然后是来自该站点的login.js源代码。我认为在js中发生的是由于某种原因,invalidHandler函数中的.validate正在运行,但submitHandler不是?提前感谢您的关注。

# enter username and password up here first
submitEl = self.find_element_by_css_selector("button[type='submit']")
submitEl.click()
self.save_screenshot('login_submission.png')

Edit2:" self"是一个继承自Webdriver.PhantomJS类的驱动程序对象。现在形式为html:

            <form class="form-login" action="" name="login" method="POST">
                <div class="errorHandler alert alert-danger no-display">
                    <i class="fa fa-remove-sign"></i> You have some form errors. Please check below.
                </div>
                                    <fieldset>
                    <div class="form-group">
                        <span class="input-icon">
                            <input type="text" class="form-control" name="username" placeholder="Username">
                            <i class="fa fa-user"></i> </span>
                    </div>
                    <div class="form-group form-actions">
                        <span class="input-icon">
                            <input type="password" class="form-control password" name="password" placeholder="Password">
                            <i class="fa fa-lock"></i>
                            <a class="forgot" href="forgot.php">
                                I forgot my password
                            </a> </span>
                    </div>
                    <div class="form-group">
                    <img src="captcha/captcha.php" alt="captcha" />
                        <span class="input-icon" style="width:200px; float: right;">
                            <input type="text" class="form-control" name="captcha">
                            <i class="fa fa-key"></i> </span>
                    </div>
                    <div class="form-actions" ><div class="slideExpandUp">
                        <label for="remember" class="checkbox-inline">
                            <input type="checkbox" class="grey remember" id="remember" name="remember">
                            Keep me signed in
                        </label>
                        <button type="submit" class="btn btn-bricky pull-right" name="submit">
                            Login <i class="fa fa-arrow-circle-right"></i>
                        </button></div>
                    </div>
                    <div class="new-account">
                        Don't have an account yet?
                        <a href="register.php" class="register">
                            Create an account
                        </a>
                    </div>
                </fieldset>
            </form>

login.js

var Login = function () {
    var runSetDefaultValidation = function () {
        $.validator.setDefaults({
            errorElement: "span", // contain the error msg in a small tag
            errorClass: 'help-block',
            errorPlacement: function (error, element) { // render error placement for each input type
                if (element.attr("type") == "radio" || element.attr("type") == "checkbox") { // for chosen elements, need to insert the error after the chosen container
                    error.insertAfter($(element).closest('.form-group').children('div').children().last());
                } else if (element.attr("name") == "card_expiry_mm" || element.attr("name") == "card_expiry_yyyy") {
                    error.appendTo($(element).closest('.form-group').children('div'));
                } else {
                    error.insertAfter(element);
                    // for other inputs, just perform default behavior
                }
            },
            ignore: ':hidden',
            highlight: function (element) {
                $(element).closest('.help-block').removeClass('valid');
                // display OK icon
                $(element).closest('.form-group').removeClass('has-success').addClass('has-error').find('.symbol').removeClass('ok').addClass('required');
                // add the Bootstrap error class to the control group
            },
            unhighlight: function (element) { // revert the change done by hightlight
                $(element).closest('.form-group').removeClass('has-error');
                // set error class to the control group
            },
            success: function (label, element) {
                label.addClass('help-block valid');
                // mark the current input as valid and display OK icon
                $(element).closest('.form-group').removeClass('has-error');
            },
            highlight: function (element) {
                $(element).closest('.help-block').removeClass('valid');
                // display OK icon
                $(element).closest('.form-group').addClass('has-error');
                // add the Bootstrap error class to the control group
            },
            unhighlight: function (element) { // revert the change done by hightlight
                $(element).closest('.form-group').removeClass('has-error');
                // set error class to the control group
            }
        });
    };
    var runLoginValidator = function () {
        var form = $('.form-login');
        var errorHandler = $('.errorHandler', form);
        form.validate({
            rules: {
                username: {
                    minlength: 2,
                    required: true
                },
                password: {
                    minlength: 6,
                    required: true
                }
            },
            submitHandler: function (form) {
                errorHandler.hide();
                form.submit();
            },
            invalidHandler: function (event, validator) { //display error alert on form submit
                errorHandler.show();
            }
        });
    };
    return {
        //main function to initiate template pages
        init: function () {
            runSetDefaultValidation();
            runLoginValidator();
        }
    };
}();

编辑:修正了标题

PhantomJS日志文件输出,请求:

PhantomJS is launching GhostDriver...
[INFO  - 2015-01-27T16:58:04.367Z] GhostDriver - Main - running on port 48152
[INFO  - 2015-01-27T16:58:05.366Z] Session [a9641420-a645-11e4-95fd-c78c9ec356b6] - page.settings - {"XSSAuditingEnabled":false,"javascriptCanCloseWindows":true,"javascriptCanOpenWindows":true,"javascriptEnabled":true,"loadImages":true,"localToRemoteUrlAccessEnabled":false,"userAgent":"Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0","webSecurityEnabled":true}
[INFO  - 2015-01-27T16:58:05.366Z] Session [a9641420-a645-11e4-95fd-c78c9ec356b6] - page.customHeaders:  - {}
[INFO  - 2015-01-27T16:58:05.366Z] Session [a9641420-a645-11e4-95fd-c78c9ec356b6] - Session.negotiatedCapabilities - {"browserName":"phantomjs","version":"1.9.8","driverName":"ghostdriver","driverVersion":"1.1.0","platform":"linux-unknown-64bit","javascriptEnabled":true,"takesScreenshot":true,"handlesAlerts":false,"databaseEnabled":false,"locationContextEnabled":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"cssSelectorsEnabled":true,"webStorageEnabled":false,"rotatable":false,"acceptSslCerts":false,"nativeEvents":true,"proxy":{"proxyType":"direct"},"phantomjs.page.settings.userAgent":"Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0"}
[INFO  - 2015-01-27T16:58:05.366Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: a9641420-a645-11e4-95fd-c78c9ec356b6
[ERROR - 2015-01-27T16:59:08.083Z] WebElementLocator - _handleLocateCommand - Element(s) NOT Found: GAVE UP. Search Stop Time: 1422377948079

最后ERROR不是我问题的一部分,而是更多的书挡。当抓取算法查找登录后显示的页面上的链接时会发生这种情况。由于我们没有成功提交登录表单,因此该链接自然不存在。

1 个答案:

答案 0 :(得分:0)

我不确定哪些更改会导致突破,但我可以说我添加了以下代码。编辑:其中只有两个是新的。删除了一个。

    webdriver.DesiredCapabilities.PHANTOMJS["phantomjs.page.settings.localToRemoteUrlAccessEnabled"] = True
    webdriver.DesiredCapabilities.PHANTOMJS["phantomjs.page.settings.browserConnectionEnabled"] = True

并且我提交了表单本身,而不是单击一个按钮(在更改上述配置之前我也曾尝试过这个)。

        formEl = self.find_element_by_css_selector("form[name='login']")
        formEl.submit()