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。
根据 documentation,您需要使用 page.event.key.Enter
而不是字符串 'Enter'
.
page.evaluate()
是沙盒页面上下文。它无法访问外部定义的变量,包括 page
和 phantom
。所以page.sendEvent()
调用必须移到外面。
那你应该在做动作之前注册回调,否则会调用错误的onUrlChanged
回调。如果加载了实际的新页面,则应使用 onLoadFinished
而不是 onUrlChanged
。
当有 CSS 个选择器时,不要使用循环。
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");
}
};
我的 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。
根据 documentation,您需要使用
page.event.key.Enter
而不是字符串'Enter'
.page.evaluate()
是沙盒页面上下文。它无法访问外部定义的变量,包括page
和phantom
。所以page.sendEvent()
调用必须移到外面。那你应该在做动作之前注册回调,否则会调用错误的
onUrlChanged
回调。如果加载了实际的新页面,则应使用onLoadFinished
而不是onUrlChanged
。当有 CSS 个选择器时,不要使用循环。
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");
}
};