我的PhantomJS脚本的目的是加载特定网站,找到搜索输入元素,在该输入中写入文本并执行搜索。从包含搜索结果的页面中,我只想抓取整个网址 - 它将包含搜索参数。
与输入交互后,我正在使用onUrlChanged()
来检测搜索结果网址何时返回。这永远不会被调用。我不知道是由于搜索未完成还是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。
答案 0 :(得分:3)
根据documentation,您需要使用page.event.key.Enter
而不是字符串'Enter'
。
page.evaluate()
是沙盒页面上下文。它无权访问外部定义的变量,其中包括page
和phantom
。因此,必须将page.sendEvent()
电话移到外面。
然后你应该在执行操作之前移动注册回调,否则会调用错误的onUrlChanged
回调。如果加载了实际的新页面,则应使用onLoadFinished
代替onUrlChanged
。
当有CSS选择器时,不要使用循环。
onUrlChange
,这并不代表网页已加载。使用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");
}
};