PhantomJS 执行搜索并获取 URL

PhantomJS performing a search and grabbing the URL

我的 PhantomJS 脚本的目的是加载特定网站、找到搜索输入元素、在该输入中写入文本并执行搜索。从包含搜索结果的加载页面中,我只想获取整个 URL - 它将包含搜索参数。

与输入交互后,我使用 onUrlChanged() 检测搜索结果 URL 何时返回。这永远不会被调用。不知道是搜索没有完成还是onUrlChanged()放错地方了

var page  = require('webpage').create(),
    response = {};
page.onUrlChanged = function(targetUrl) { // Page loaded
    page.evaluate(function() {
        var inputs = document.getElementsByTagName('input');
        for (var i = 0; i < inputs.length; i++) {
            if (inputs[i].type.toLowerCase().indexOf('search') > -1) {
                inputs[i].value = 'cat dog';
                inputs[i].focus();
                page.sendEvent('keypress', 'Enter');
                break;
            }
        }
    });

    // This does not get called
    page.onUrlChanged = function(targetUrl) { // Search result loaded
        response.content = targetUrl;
        console.log(JSON.stringify(response));
        phantom.exit(1);
    };
};

page.open('http://www.mysearch.com/', function(status) {
    if (status !== 'success') {
        response.content = 'Unable to access network';
        console.log(JSON.stringify(response));
        phantom.exit(1);
    } else {
        phantom.exit(1);
    }
});

注意:我知道 CasperJS 更擅长这种用例,但是在我当前的环境中我必须使用 PhantomJS。

  1. 根据 documentation,您需要使用 page.event.key.Enter 而不是字符串 'Enter'.

  2. page.evaluate() 是沙盒页面上下文。它无法访问外部定义的变量,包括 pagephantom。所以page.sendEvent()调用必须移到外面。

  3. 那你应该在做动作之前注册回调,否则会调用错误的onUrlChanged回调。如果加载了实际的新页面,则应使用 onLoadFinished 而不是 onUrlChanged

  4. 当有 CSS 个选择器时,不要使用循环。

  5. onUrlChange 在 URL 发生变化时触发,这并不意味着页面已经加载。使用 onLoadFinished 等待页面加载完成(不包括动态 JS)。此外,带回调的 page.open() 与将回调注册到 onLoadFinished 并在没有回调的情况下调用 page.open() 相同。

最终完整代码:

var page  = require('webpage').create(),
    response = {};
page.open('http://www.mysearch.com/', function(status) {
    if (status !== 'success') {
        response.content = 'Unable to access network';
        console.log(JSON.stringify(response));
        phantom.exit(1);
    }
    var exists = page.evaluate(function() {
        var input = document.querySelector('input[type*="search"]');
        if (input) {
            input.value = 'cat dog';
            input.focus();
        }
        return !!input;
    });
    page.onLoadFinished = function(status) { // Search result loaded
        console.log("new page loaded with status: " + status);
        phantom.exit();
    };
    if (exists) {
        page.sendEvent('keypress', page.event.key.Enter);
    } else {
        console.log("field not found");
    }
};