Casperjs ajax 调用 - waitForResource 和解析错误
Casperjs ajax calls - waitForResource and parse errors
Casperjs 是一个很棒的工具。我已经能够理解某些基础知识。但是,我正在尝试解决两个问题。首先,出于关闭原因,我将我的代码拆分为几个函数。我收到一个解析错误。我已将选项添加到 verbose: true, logLevel: "debug"
并查看它是否指出行号但我没有得到任何结果。其次,我想进行一个异步的 ajax 调用。我正在使用 waitFor
但我阅读了 THIS 文章以获得更有效的方法。如何设置 waitForResource()
以跟踪 AJAX 请求?以及如何显示解析错误行?
代码
var urls = ['http://9gag.tv/'];
var casper = require('casper').create({
verbose: true,
logLevel: "debug"
});
function getNumberOfItems(casper) {
return casper.getElementsInfo(".listview .badge-grid-item").length;
}
function tryAndScroll(casper) {
casper.page.scrollPosition = { top: casper.page.scrollPosition["top"] + 4000, left: 0 };
var info = casper.getElementInfo('.badge-post-grid-load-more');
if (info.visible) {
var curItems = getNumberOfItems(casper);
if( curItems <= 60 ) {
casper.waitFor(function check(){
return curItems != getNumberOfItems(casper);
}, function then(){
tryAndScroll(this);
}, function onTimeout(){
this.echo("Timout reached");
}, 10000);
}
} else {
casper.echo("no more items");
}
}
function combineArrays(x, y) {
var result = [];
for(var i = 0, i < page_links.length; i++) {
result[i] = {};
result[i].page_link = x[i];
result[i].video_link = y[i];
}
return result;
}
function linkScraper(x){
var page_links = [];
var youtube = [];
for (var i = 0; i < x.length; i++)
{ // start for loop
casper.thenOpen(x[i], function() {
//Scroll down for elements
tryAndScroll(this);
casper.then(function() {
this.getElementsInfo('.title').forEach(function(element) {
// skip elements that don't have a href attribute...
if (!element.attributes.href) {
return;
}
page_links.push( element["attributes"]["href"] );
casper.thenOpen(element.attributes.href, function() {
this.click('.responsivewrapper');
}).then(function(){
casper.each(this.getElementsInfo('.badge-youtube-player'), function(casper, element, j) {
youtube.push( element["attributes"]["src"] );
});
})localhost;
});
});
});
}
return combineArrays(page_links,youtube);
}
function stringifyResult(webpages){
//Pass link array to linkScraper
var linksArr = linkScraper.call(this, webpages);
//send results to php page
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.waitFor( function() {
response = this.evaluate(function() {
$.ajax({
type: "POST",
url: server,
data: JSON.stringify(linksArr),
//dataType: 'json',
contentType: "application/json",
success: function (data) {
this.echo("All done.");
return this.exit();
//return data.responseText;
},
error: function (xhr,status,error){
return this.echo(error);
}
});
});
});
}
casper.start().then(function() {
this.echo("Starting");
});
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.run(stringifyResult.call(this, urls));
你的代码有很多问题。
1。语法错误
CasperJS 和 PhantomJS 本身不会告诉你语法错误在哪里,但它可能在 for(var i = 0, i < page_links.length; i++) {
行。将 ,
更改为 ;
。并且 page_links
未在此行中定义。你的意思可能是 x
.
对于未来:CasperJS 脚本是普通的 JavaScript。您可以使用 jslint.com 等在线工具来查找此类错误(以及代码的其他问题)。
还有个错位localhost
.
2。 this
this
根据放置的位置有很多含义。
a) 全球 this
以最后一行为例:
casper.run(stringifyResult.call(this, urls));
这个this
在所有函数之外。所以它指的是 window
(是的,有两个单独的 window
对象,一个在页面上下文内部,一个在页面上下文外部)。它没有提到您可能期望的 casper
。使用:
casper.run(stringifyResult.call(casper, urls));
(^非最终代码:见6.)
b) jQuery 回调
里面的this
:
success: function (data) {
this.echo("All done.");
return this.exit();
},
指的是 jQuery 的 jqXHR
对象(顺便说一句,你也不能 return 来自函数内部的异步函数的东西)。它与 CasperJS 无关。此外,不可能从页面上下文(casper.evaluate()
内部)调用 CasperJS 函数,因为页面上下文是沙箱化的。它无法访问外部定义的变量(包括 linksArr
和 server
)。有关详细信息,请参阅 this。
3。不必要的 waitFor
您的 waitFor
永远不会完成,但您可能以这种方式设计它以便发送您的 AJAX 请求。问题是每 20 毫秒将发送相同的损坏请求。
4。发送 AJAX 请求
CasperJS 提供了一个在页面上下文中发送 AJAX 请求的实用程序:__utils__.sendAJAX()
。它还默认阻止执行,因此无需以越界方式等待请求。
function stringifyResult(webpages){
var linksArr = linkScraper.call(this, webpages);
//send results to php page
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.evaluate(function(server, linksArr){
__utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
}, server, linksArr);
}
(^非最终代码:见5.)
5。从异步函数返回
所有 then*
和 wait*
CasperJS 函数都是异步的。通过调用它们,您可以安排相关步骤在当前步骤结束时执行。
这意味着你不能 return 来自 linkScraper
的东西,因为它包含异步代码。或者至少你不能 return 最终结果,因为它们是由异步代码填充的。但是,您可以 return 最终包含结果的数组。
一个可能的修复方法是将 combine 调用移到 linkScraper
:
之外
function linkScraper(x){
var page_links = [];
var youtube = [];
// here are asynchronous calls
return {pl: page_links, yt: youtube};
}
function stringifyResult(webpages){
var linksObj = linkScraper.call(this, webpages);
// here linksObj contains empty lists
this.then(function(){
// here linksObj contains populated lists
var linksArr = combineArrays(linksObj.pl, linksObj.yt);
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.evaluate(function(server, linksArr){
__utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
}, server, linksArr);
});
}
6。 exit
casper.exit()
是即时的。所以当你调用它时,执行就会停止。调用的时候一定要小心,因为有可能还有预定的步数。
有一种方法可以通过不向 casper.run()
提供回调来避免调用 casper.exit()
。如果你提供这样的回调,所有步骤都执行完就不会自动退出了。
casper.then(stringifyResult.call(casper, urls)).run();
Casperjs 是一个很棒的工具。我已经能够理解某些基础知识。但是,我正在尝试解决两个问题。首先,出于关闭原因,我将我的代码拆分为几个函数。我收到一个解析错误。我已将选项添加到 verbose: true, logLevel: "debug"
并查看它是否指出行号但我没有得到任何结果。其次,我想进行一个异步的 ajax 调用。我正在使用 waitFor
但我阅读了 THIS 文章以获得更有效的方法。如何设置 waitForResource()
以跟踪 AJAX 请求?以及如何显示解析错误行?
代码
var urls = ['http://9gag.tv/'];
var casper = require('casper').create({
verbose: true,
logLevel: "debug"
});
function getNumberOfItems(casper) {
return casper.getElementsInfo(".listview .badge-grid-item").length;
}
function tryAndScroll(casper) {
casper.page.scrollPosition = { top: casper.page.scrollPosition["top"] + 4000, left: 0 };
var info = casper.getElementInfo('.badge-post-grid-load-more');
if (info.visible) {
var curItems = getNumberOfItems(casper);
if( curItems <= 60 ) {
casper.waitFor(function check(){
return curItems != getNumberOfItems(casper);
}, function then(){
tryAndScroll(this);
}, function onTimeout(){
this.echo("Timout reached");
}, 10000);
}
} else {
casper.echo("no more items");
}
}
function combineArrays(x, y) {
var result = [];
for(var i = 0, i < page_links.length; i++) {
result[i] = {};
result[i].page_link = x[i];
result[i].video_link = y[i];
}
return result;
}
function linkScraper(x){
var page_links = [];
var youtube = [];
for (var i = 0; i < x.length; i++)
{ // start for loop
casper.thenOpen(x[i], function() {
//Scroll down for elements
tryAndScroll(this);
casper.then(function() {
this.getElementsInfo('.title').forEach(function(element) {
// skip elements that don't have a href attribute...
if (!element.attributes.href) {
return;
}
page_links.push( element["attributes"]["href"] );
casper.thenOpen(element.attributes.href, function() {
this.click('.responsivewrapper');
}).then(function(){
casper.each(this.getElementsInfo('.badge-youtube-player'), function(casper, element, j) {
youtube.push( element["attributes"]["src"] );
});
})localhost;
});
});
});
}
return combineArrays(page_links,youtube);
}
function stringifyResult(webpages){
//Pass link array to linkScraper
var linksArr = linkScraper.call(this, webpages);
//send results to php page
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.waitFor( function() {
response = this.evaluate(function() {
$.ajax({
type: "POST",
url: server,
data: JSON.stringify(linksArr),
//dataType: 'json',
contentType: "application/json",
success: function (data) {
this.echo("All done.");
return this.exit();
//return data.responseText;
},
error: function (xhr,status,error){
return this.echo(error);
}
});
});
});
}
casper.start().then(function() {
this.echo("Starting");
});
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.run(stringifyResult.call(this, urls));
你的代码有很多问题。
1。语法错误
CasperJS 和 PhantomJS 本身不会告诉你语法错误在哪里,但它可能在 for(var i = 0, i < page_links.length; i++) {
行。将 ,
更改为 ;
。并且 page_links
未在此行中定义。你的意思可能是 x
.
对于未来:CasperJS 脚本是普通的 JavaScript。您可以使用 jslint.com 等在线工具来查找此类错误(以及代码的其他问题)。
还有个错位localhost
.
2。 this
this
根据放置的位置有很多含义。
a) 全球 this
以最后一行为例:
casper.run(stringifyResult.call(this, urls));
这个this
在所有函数之外。所以它指的是 window
(是的,有两个单独的 window
对象,一个在页面上下文内部,一个在页面上下文外部)。它没有提到您可能期望的 casper
。使用:
casper.run(stringifyResult.call(casper, urls));
(^非最终代码:见6.)
b) jQuery 回调
里面的this
:
success: function (data) {
this.echo("All done.");
return this.exit();
},
指的是 jQuery 的 jqXHR
对象(顺便说一句,你也不能 return 来自函数内部的异步函数的东西)。它与 CasperJS 无关。此外,不可能从页面上下文(casper.evaluate()
内部)调用 CasperJS 函数,因为页面上下文是沙箱化的。它无法访问外部定义的变量(包括 linksArr
和 server
)。有关详细信息,请参阅 this。
3。不必要的 waitFor
您的 waitFor
永远不会完成,但您可能以这种方式设计它以便发送您的 AJAX 请求。问题是每 20 毫秒将发送相同的损坏请求。
4。发送 AJAX 请求
CasperJS 提供了一个在页面上下文中发送 AJAX 请求的实用程序:__utils__.sendAJAX()
。它还默认阻止执行,因此无需以越界方式等待请求。
function stringifyResult(webpages){
var linksArr = linkScraper.call(this, webpages);
//send results to php page
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.evaluate(function(server, linksArr){
__utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
}, server, linksArr);
}
(^非最终代码:见5.)
5。从异步函数返回
所有 then*
和 wait*
CasperJS 函数都是异步的。通过调用它们,您可以安排相关步骤在当前步骤结束时执行。
这意味着你不能 return 来自 linkScraper
的东西,因为它包含异步代码。或者至少你不能 return 最终结果,因为它们是由异步代码填充的。但是,您可以 return 最终包含结果的数组。
一个可能的修复方法是将 combine 调用移到 linkScraper
:
function linkScraper(x){
var page_links = [];
var youtube = [];
// here are asynchronous calls
return {pl: page_links, yt: youtube};
}
function stringifyResult(webpages){
var linksObj = linkScraper.call(this, webpages);
// here linksObj contains empty lists
this.then(function(){
// here linksObj contains populated lists
var linksArr = combineArrays(linksObj.pl, linksObj.yt);
server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
this.evaluate(function(server, linksArr){
__utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
}, server, linksArr);
});
}
6。 exit
casper.exit()
是即时的。所以当你调用它时,执行就会停止。调用的时候一定要小心,因为有可能还有预定的步数。
有一种方法可以通过不向 casper.run()
提供回调来避免调用 casper.exit()
。如果你提供这样的回调,所有步骤都执行完就不会自动退出了。
casper.then(stringifyResult.call(casper, urls)).run();