Tri*_*daz 66 node.js web-scraping jsdom phantomjs
我正在计划内部使用的webservice,它接受一个参数,一个URL,并返回表示该URL中已解析 DOM的html .通过解决,我的意思是webservice将首先获取该URL的页面,然后使用PhantomJS"渲染"页面,然后在执行所有DHTML,AJAX调用等之后返回结果源.但是发动对每个请求的基础(这是我现在做)幽灵的方式过于缓慢.我宁愿拥有一个PhantomJS实例池,其中一个实例可用于为我的webservice提供最新的调用.
以前有没有做过这方面的工作?我宁愿将这个web服务基于其他人的工作,而不是从头开始为我自己编写一个池管理器/ http代理服务器.
更多上下文:我列出了迄今为止我见过的两个类似的项目,以及为什么我避免了每个项目,这导致了关于管理PhantomJS实例池的问题.
jsdom - 从我所看到它在页面上执行脚本具有很强的功能,但它不会尝试复制浏览器行为,因此如果我将它用作通用的"DOM解析器",那么它最终会成为很多额外的编码来处理各种边缘情况,事件调用等.我看到的第一个例子是必须为我使用node设置的测试应用程序手动调用body标签的onload()函数.这似乎是一个深深的兔子洞的开始.
Selenium - 它只有很多移动部件,因此设置一个池来管理长期存在的浏览器实例将比使用PhantomJS更复杂.我不需要它的任何宏录制/脚本功能.我只想要一个能够获得网页并解析它的DOM的web服务,就好像我用浏览器浏览到那个URL一样(如果我可以让它忽略图像等,甚至更快)
Jas*_*onS 62
我设置了一个PhantomJs Cloud Service,它几乎可以满足您的要求.我花了大约5个星期的工作时间.
您将遇到的最大问题是PhantomJs中已知的内存泄漏问题.我解决这个问题的方法是每50次调用循环我的实例.
您将遇到的第二大问题是每页处理非常CPU和内存密集,因此您每个CPU只能运行4个左右的实例.
你遇到的第三大问题是PhantomJs在页面完成事件和重定向方面非常古怪.您将被告知您的页面在实际呈现之前已完成呈现. 有很多方法可以解决这个问题,但遗憾的是没有任何"标准".
你要处理的第四大问题是nodejs和phantomjs之间的互操作,幸好有很多npm软件包可以解决这个问题.
所以我知道我有偏见(因为我写了我要建议的解决方案),但我建议你查看PhantomJsCloud.com,它可以免费使用.
2015年1月更新:我遇到的另一个(第五个?)大问题是如何从经理/负载均衡器发送请求/响应.最初我使用的是PhantomJS的内置HTTP服务器,但仍然遇到了它的局限性,特别是在最大响应大小方面.我最终将请求/响应写入本地文件系统作为通信线路. *实施服务所花费的总时间可能代表20个人周问题,也许是1000个小时的工作.*和FYI我正在为下一个版本进行完全重写....(正在进行中)
Mic*_*ley 17
该JavaScript库的异步工作在节点和具有queue
功能是这种东西非常方便:
queue(worker, concurrency)
使用指定的并发创建队列对象.添加到队列中的任务将并行处理(最高为并发限制).如果所有工作人员都在进行中,则该任务将排队等候,直到有一个工作可用.一旦工作人员完成任务,就会调用任务的回调.
一些伪代码:
function getSourceViaPhantomJs(url, callback) {
var resultingHtml = someMagicPhantomJsStuff(url);
callback(null, resultingHtml);
}
var q = async.queue(function (task, callback) {
// delegate to a function that should call callback when it's done
// with (err, resultingHtml) as parameters
getSourceViaPhantomJs(task.url, callback);
}, 5); // up to 5 PhantomJS calls at a time
app.get('/some/url', function(req, res) {
q.push({url: params['url_to_scrape']}, function (err, results) {
res.end(results);
});
});
Run Code Online (Sandbox Code Playgroud)
Tho*_*orf 14
对于我的硕士论文,我开发了图书馆phantomjs-pool,正是这样做的.它允许提供作业,然后映射到PhantomJS工作人员.该库处理作业分发,通信,错误处理,日志记录,重新启动等等.该库已成功用于抓取超过一百万页.
例:
以下代码执行Google搜索数字0到9,并将页面屏幕截图保存为googleX.png.四个网站并行爬行(由于创建了四个工作人员).脚本通过启动node master.js
.
master.js(在Node.js环境中运行)
var Pool = require('phantomjs-pool').Pool;
var pool = new Pool({ // create a pool
numWorkers : 4, // with 4 workers
jobCallback : jobCallback,
workerFile : __dirname + '/worker.js', // location of the worker file
phantomjsBinary : __dirname + '/path/to/phantomjs_binary' // either provide the location of the binary or install phantomjs or phantomjs2 (via npm)
});
pool.start();
function jobCallback(job, worker, index) { // called to create a single job
if (index < 10) { // index is count up for each job automatically
job(index, function(err) { // create the job with index as data
console.log('DONE: ' + index); // log that the job was done
});
} else {
job(null); // no more jobs
}
}
Run Code Online (Sandbox Code Playgroud)
worker.js(在PhantomJS环境中运行)
var webpage = require('webpage');
module.exports = function(data, done, worker) { // data provided by the master
var page = webpage.create();
// search for the given data (which contains the index number) and save a screenshot
page.open('https://www.google.com/search?q=' + data, function() {
page.render('google' + data + '.png');
done(); // signal that the job was executed
});
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23248 次 |
最近记录: |