网站首页
网站导航
Ctrl+D收藏
首 页
代码段
源码包
文档库
工具箱
代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
JS
】
spider
作者:
Rogee
/ 发布于
2015/3/5
/
422
从第一个url开始爬取,遍历所有取得的url
/** * New node file */ var http = require('http'); var urlModule=require('url'); var fs=require('fs'); var timers=require('timers'); var iconv=require('iconv-lite'); var cheerio=require('cheerio'); var moment=require('moment'); var redis = require("redis"), client = redis.createClient(); var hash=require('../modules/hash'); var mysqlpool=require('../modules/mysqlpool')(); var SimpleQuene=require('../modules/SimpleQuene'); var globalObj={ initurl:"http://www.oschina.net/", tempfilepath:'E:/1.txt', lengthflag:true, queneLength:10000 //最小值5000 } var regArr=[/charset\s*=\s*[a-z | A-Z | 0-9 | -]*(['|"|\s]){0,1}/,/charset\s*=\s*/]; //匹配编码的正则 var init=function(){ client.multi().rpush('waitquene',globalObj.initurl) // .rpush('dealquene','') .exec(function(err, replies){ console.log('quene inited'); }); } // 解析页面,获取url var resolve=function(url,content){ var $=cheerio.load(content); var hrefs=[]; var host=''; var title=$('head').find('title').text(); // 保存本次爬取信息 if(!title){ return; } // 使用这种方式进行数据保存 ,当在数据保存文件时,进行字符串连接将会花去大量的时间(20w以上时) client.hmset(url,{ 'url':url, 'title':title, 'time':moment().format('YYYY-MM-DD h:mm:ss') }); client.multi().llen('waitquene').rpush('dealquene',url).llen('dealquene').exec(function(err,lenarr){ if(lenarr[0]+$('a').length>globalObj.queneLength-1){ globalObj.lengthflag=false; } if(lenarr[0]==5){ globalObj.lengthflag=true; } var tempQuene=new SimpleQuene(); if(globalObj.lengthflag){ // 去除重页面获取的url中重复值 $('a').each(function(i,item){ host=urlModule.parse(($(item).attr('href') || "").replace(/\s/g,'')).host; if(host && host!='null'){ if(!tempQuene.contains(host)){ tempQuene.in(host); } } }); // 进入等待队列 while(!tempQuene.isEmpty()){ (function(param){ //在以爬队列和等待队列中判断重复 client.multi().hexists(param,'url').exec(function (err,exists) { if('0'==exists[0]){ client.rpush('waitquene',param); } }); })(tempQuene.out()); } } console.log("waitquene size:"+lenarr[0]+" add:"+tempQuene.size()+" dealquene size:"+lenarr[2]+' '+url+" "+title); }); } // 发起url请求 var start=function(serachurl){ // console.log("get "+serachurl+" "); if(serachurl.indexOf('http://')<0){ serachurl="http://"+serachurl; } var templist=[]; var buflength=0; var req=http.get(serachurl,function(res){ //获取编码 var charset=(res.headers['content-type'] || '').match(regArr[0]) || ['']; var encoding=(charset[0].split(regArr[1])[1]) || 'utf-8'; res.on('data',function(data){ buflength+=data.length; templist.push(data); // 将buffer存入数组中 代替html+=data }); res.on('end',function(){ timers.clearTimeout(timeout); // 最后进行buffer数组连接操作 效率优于使用html+=data var html =iconv.decode(Buffer.concat(templist, buflength), encoding); if(html){ resolve(serachurl,html); } }); }); // 设置连接超时 var timeout=timers.setTimeout(function(){ req.emit('error','request time out'); },2000); req.on('error',function(err){ console.log(" error get "+serachurl +" with "+err+" "); }) }; // 从等待队列中获取url var search=function(){ var index=timers.setInterval(function(){ client.multi().llen('waitquene').lpop('waitquene').exec(function(err,result){ if(result[0]>0){ start(result[1]); } }); },1); } var waitsaveData=function(){ var index=timers.setInterval(function(){ client.llen('dealquene',function(err,size){ console.log('dealed url quene size '+size); if(size==globalObj.queneLength-1000){ saveToMysql(); } }); },2000); } // 保存数据到mysql var saveToMysql=function(){ multi = client.multi(); for(var i=0;i<globalObj.queneLength;i++){ multi.lpop('dealquene'); } multi.exec(function (err, urlArr) { multigetData = client.multi(); for(var j=0;j<urlArr.length;j++){ multigetData.hgetall(urlArr[j]); } multigetData.exec(function(err,dataArr){ save(dataArr,globalObj.tempfilepath); }); }); } // 将数据写入文件,然后使用load data infile方式读入mysql var save=function(objArr,path){ var writer=fs.createWriteStream(path); console.time('fs'); for(var i=0;i<objArr.length;i++){ var temp=objArr[i]; if(temp){ urlhash=hash.fnv1a(temp.url); writer.write(temp.url+','+(urlhash || "")+','+(temp.title || '""')+','+(temp.time || '""')+"\n"); } } writer.end(function(){ console.timeEnd('fs'); console.time('sql'); var sql="load data infile '"+path+ "' replace into table spider_page FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' (url,urlhash,title,time)"; var mysqlpool=require('../modules/mysqlpool')(); mysqlpool.query(sql,function(err,result){ console.timeEnd('sql'); console.log(result.affectedRows+' rows have been insert'); }); }); } init(); search(); //saveToMysql(); SimpleQuene.js var SimpleQuene=function(len){ var capacity=len; var list=[]; this.in=function(data){ if(!data){return false;} if(list.length == capacity){ this.out(); } list.push(data); return true; }; this.out=function(){ return list.splice(0,1)[0]; } this.isEmpty=function(){ return list.length==0?true:false; } this.size=function(){ return list.length; } this.containsHash=function(hash){ var result=false; for(var i=0;i<list.length;i++){ if(hash==list[i].hash){ result=true; break; } } return result; } this.contains=function(url){ var result=false; for(var i=0;i<list.length;i++){ if(list[i].indexOf(url)>=0){ result=true; break; } } return result; } } module.exports = SimpleQuene;
评论列表
本站所提供的代码,版权归原作者所有,若有侵犯作者版权,请与我们联系,我们将立即删除或修改。谢谢!
本站所有代码发布及提供者。
试试其它关键字
spider
同语言下
.
Jquery搜索框获取回车事件
.
H5页面添加倒计时,然后自动跳转
.
通过user-agent判断h5页面是在哪个手机App(QQ、微信
.
nginx 禁止未绑定的域名访问
.
JavaScript 获取按键,并屏蔽系统 Window 事件
.
H5之只允许微信浏览器打开,禁止从外部浏览器访问
.
微信打开网址添加在浏览器中打开提示的办法
.
实现JS复制、粘贴,Chrome/Firefox下可用
.
video视频播放,play()、pause()、duration时长、onen
.
HTML5实现MP3上传前的预览和播放时长的获取
可能有用的
.
SQL查询 多列合并成一行用逗号隔开
.
一行一行读取txt的内容
.
C#动态修改文件夹名称(FSO实现,不移动文件)
.
c# 移动文件或文件夹
.
c#图片添加水印
.
Java PDF转换成图片并输出给前台展示
.
网站后台修改图片尺寸代码
.
处理大图片在缩略图时的展示
.
实现对图片上传的接收
.
判断用户输入的是否为IP地址
Rogee
贡献的其它代码
(
1
)
.
spider
地图
本站
我们
服务
版权
联系
回馈
博客