用nodejs写了个测试爬虫,发现效率很慢,难道是我写的问题!
发布于 1年前 作者 qq444139212 1999 次浏览

用到了https://github.com/scottkiss/nodegrass插件 环境

root:~# node -v
v0.11.9-pre
root:~# cat /etc/issue
Ubuntu 12.04.3 LTS \n \l

测试发现,每隔5秒才有4个请求被执行,也就是相当于4个线程。应该是还没4个线程的高效,因为分2部请求url,也就是每个4个请求要5秒的等待,还是线性等待的。

请指教下,怎样写才能达到最优效果,要是多步url抓取应该怎么优化?

var VideoInfo = function(){
 var videoName,
  videoType,
  directory,
  actor,
  area,
  type,
  year,
  lang,
  summary,
  image,
  size,
  playcount,
  itemList; 
}

var ItemData = function(){
 var mvSize,
  vlomeName,
  pic,
  summary,
  urlList;
}

var UrlInfo = function(){
 var url,
  website;
}

var nodegrass = require('nodegrass');
var dt = new Date().getTime();

var getVideoInfo = function(year,page){
 nodegrass.get("http://list.letv.com/api/chandata.json?c=1&d=1&md=&o=20&ph=1&s=1&y=" + year + "&p=" + page,function(data,status,headers){
  var list = JSON.parse(data).data_list;
  for(var i = 0;i < list.length; i++){
   var obj = list[i];
   var info = new VideoInfo();
   info.videoName = obj.name;
   info.videoType = obj.categoryName;
   info.directory = obj.directory;
   info.actor = obj.starring;
   info.area = obj.areaName;
   info.type = obj.subCategoryName;
   info.year = new Date(obj.releaseDate).getFullYear();
   info.lang = obj.lgName;
   info.summary = obj.description;
   info.image = obj.poster20;
   info.size = obj.ipadCount;
   info.playcount = obj.directory;
   getUrlList(info,obj.aid);
  }  
  console.info(11111);  
 },'utf8').on('error', function(e) {
  console.log("Got error: " + e.message);
 });
}

var getUrlList = function(info,vid){
 info.itemList = [];
 nodegrass.get("http://app.letv.com/ajax/getFocusVideo.php?jsonp=&pid="+vid+"&p=1&top=0&max=10000",function(data,status,headers){
  data = data.substring(1,data.length-1);
  data = unescape(data.replace(/\\u/gi, '%u'));
  var json = JSON.parse(data);
  for(var i = 0;i < json.length; i++){ 
   var obj = json[i];
   var item = new ItemData();
   item.mvSize = obj.key;
   item.vlomeName = "第"+obj.key+"集";
   item.pic = obj.pic;
   item.summary = obj.title;
   var urlobj = new UrlInfo();
   urlobj.url = obj.url;
   urlobj.website = "letv";
   item.urlList = [];
   item.urlList.push(urlobj);
   info.itemList.push(item);
  }
  console.info(22222);
  console.info((new Date().getTime()-dt));
 },'utf8').on('error', function(e) {
  console.log("Got error: " + e.message);
 });
}

for(var year = 2013;year>=2009;year--){
 for(var page = 1; page<=15;page++){
  console.info(year+":"+page);
  getVideoInfo(year,page);
 }
}
11 回复

爬页面用 https://github.com/mikeal/request

https://github.com/MatthewMueller/cheerio

这个组合应该还算给力,还有就是node 是单线程的…你得多进程的去爬…

多进程,那不还是相当于多线程,我以为说node的事件驱动完全可以比拟多线程了!看来还是有限制的。 现在就觉得事件驱动和生产消费者模式差不多了!

@qq444139212 …对于这点…我没怎么仔细测试过,不评论这点…我觉得如果,你专注于Node.js 的性能的话,要不为了广大群众,写一份报告…目前已有的资料都是Node.js 肯定 比 php 强…

@qq444139212 用http.request这个方法去实现异步爬虫, node的底层是用的libuv, 最好了解一下libuv的运行原理吧, 感觉你对node的理解就是误解,个人观点

关于nodegrass,我稍稍完善了一下,当然不是效率上的完善,而是指使用上面的。之前push到作者的主分支,但是作者长时间没上,我自己弄了个nodegrassex。现在已经合并到主分支了,但是估计作者在npm官网上没更新,所以你可以在项目中使用:

$ npm install nodegrassex

项目主页是:

https://github.com/XadillaX/nodegrass

不需要自己处理抓资料的细节代码,现成的wget多好用啊

wget支持各种header么?比如说cookie什么的

@mayflower 嗯,我看看,才接触node,以前一直js,感觉上js事件触发是多点触发,虽然事件冒泡,但每个事件之间没耦合。然后用node就感觉,整个流程还是线性的,只是在涉及io处理方面做成了异步回调。但是同一个事件触犯后还是要等待上一个回调完才能继续执行,node内部线程只有4个,也就是相当每次只能有4个事件并行运行!看了看多进程,还没怎么弄懂,现在学习中!

好的,谢谢。刚刚接触node,以后请多指教

我这里其实就爬取一个json,然后自己解析, 【入库】。 很简单,其实是想测试下node的运行原理,以及易用性。^^

回到顶部