【发布时间】:2018-03-04 10:25:14
【问题描述】:
我编写了一个运行良好的 CasperJS 脚本,只是它需要(非常非常)很长的时间来抓取页面。
简而言之,这是伪代码:
- 我的功能来抓取元素
- 我的
casper.start()开始导航并登录 -
casper.then()我循环遍历一个数组并存储我的链接 -
casper.thenOpen()打开每个链接并调用我的函数来报废。
它可以完美地(并且足够快)抓取一堆链接。但是当涉及到数千个时(现在我正在运行包含 100K 链接数组的脚本),执行时间是无穷无尽的:前 10K 链接在 3h54m10s 中被废弃,接下来的 10K 在 2h18m27s 中被废弃。
我可以稍微解释一下这两个 10K 批次之间的区别:第一个包括带有 100K 链接的数组的循环和存储。从这一点开始,脚本只打开页面来废弃它们。但是,我注意到阵列在大约 30 分钟后准备就绪,因此无法准确解释时间间隔。
我已将我的casper.thenOpen() 放在 for 循环中,希望在每个新链接构建并存储在数组中之后,会发生报废。现在,我确定我失败了,但它会在性能方面改变什么吗?
这是我现在想到的唯一线索,如果有人愿意分享他/她的最佳实践以显着减少脚本执行的运行时间(应该不难!),我将非常感激。
编辑#1
下面是我的代码:
var casper = require('casper').create();
var fs = require('fs');
// This array maintains a list of links to each HOL profile
// Example of a valid URL: https://myurl.com/list/74832
var root = 'https://myurl.com/list/';
var end = 0;
var limit = 100000;
var scrapedRows = [];
// Returns the selector element property if the selector exists but otherwise returns defaultValue
function querySelectorGet(selector, property, defaultValue) {
var item = document.querySelector(selector);
item = item ? item[property] : defaultValue;
return item;
}
// Scraping function
function scrapDetails(querySelectorGet) {
var info1 = querySelectorGet("div.classA h1", 'innerHTML', 'N/A').trim()
var info2 = querySelectorGet("a.classB span", 'innerHTML', 'N/A').trim()
var info3 = querySelectorGet("a.classC span", 'innerHTML', 'N/A').trim()
//For scraping different texts of the same kind (i.e: comments from users)
var commentsTags = document.querySelectorAll('div.classComments');
var comments = Array.prototype.map.call(commentsTags, function(e) {
return e.innerText;
})
// Return all the rest of the information as a JSON string
return {
info1: info1,
info2: info2,
info3: info3,
// There is no fixed number of comments & answers so we join them with a semicolon
comments : comments.join(' ; ')
};
}
casper.start('http://myurl.com/login', function() {
this.sendKeys('#username', 'username', {keepFocus: true});
this.sendKeys('#password', 'password', {keepFocus: true});
this.sendKeys('#password', casper.page.event.key.Enter, {keepFocus: true});
// Logged In
this.wait(3000,function(){
//Verify connection by printing welcome page's title
this.echo( 'Opened main site titled: ' + this.getTitle());
});
});
casper.then( function() {
//Quick summary
this.echo('# of links : ' + limit);
this.echo('scraping links ...')
for (var i = 0; i < limit; i++) {
// Building the urls to visit
var link = root + end;
// Visiting pages...
casper.thenOpen(link).then(function() {
// We pass the querySelectorGet method to use it within the webpage context
var row = this.evaluate(scrapDetails, querySelectorGet);
scrapedRows.push(row);
// Stats display
this.echo('Scraped row ' + scrapedRows.length + ' of ' + limit);
});
end++;
}
});
casper.then(function() {
fs.write('infos.json', JSON.stringify(scrapedRows), 'w')
});
casper.run( function() {
casper.exit();
});
【问题讨论】:
标签: arrays performance time casperjs execution