nodejs写的一个网页爬虫例子(坏链率)

因为工作需要,用nodejs写了个简单的爬虫例子,之前也没用过nodejs,连搭环境加写大概用了5天左右,so。。。要多简陋有多简陋,放这里给以后的自己看~~

整体需求是:给一个有效的URL地址,返回该网页上所有无效链接的百分比(坏链率)

第一个文件:计算环链率 urlSpider.js


  1 /*================================================
2 @author MissUU
3 链接抓取思路:
4
5 1. 获取页面内容
6 2. 正则取得所有<a>
7 3. 进一步取得href属性值,如果首位是“则剔除,不是http开头加上域名(javascript开头除外)
8 4.正则验证是否是常见URL格式
9 ================================================*/
10 var http = require(‘http‘);
11 var async = require(‘async‘);
12 var dbHandle = require(‘./dbHandle.js‘);
13
14 //主程序
15 var runUrlSpider = function(obj, callback){
16 //10s timeout
17 var request_timer = setTimeout(function() {
18 req.abort();
19 console.log(‘Request Timeout.‘);
20 }, 10000);
21
22 var urlBadLink = new UrlBadLink();
23 var html=‘‘;
24 var req = http.get(obj.url, function(res) {
25
26 clearTimeout(request_timer);
27
28 res.setEncoding(‘utf8‘);
29 res.on(‘data‘, function (chunk) {
30 html += chunk;
31 }).on(‘end‘, function(){
32 console.log(‘*******开始提取有效链接地址******‘);
33 console.log(new Date().toLocaleString());
34 console.log(obj.url);
35 urlBadLink.host = obj.url;
36 urlBadLink.id = obj.id;
37 matchURL(html, urlBadLink, function(){
38 callback();
39 });
40 });
41 });
42
43 req.on(‘error‘, function(e) {
44 console.log(‘problem with request: ‘ + e.message);
45 callback();
46 });
47 }
48
49 //this is the entrance of code
50 var main = function(){
51 var urlArray = dbHandle.showUrls(1, function(result){
54 async.eachSeries(result, runUrlSpider, function(err){
55 console.log(‘******this is the end, haha*******‘);
56 });
57 });
58 // console.log(urlArray);
59
60 };
61
62 main();
63
64 /*
65 * 用于异步放送get请求
66 *
67 * @param {string} content 原始页面信息
68 * @param {string} host 主域名
69 */
70 function matchURL(content, urlBadLink, callend){
71 var host = urlBadLink.host;
72 var anchor = /<a\s[^>]*>/g;
73 var matches = content.match(anchor);
74 var badLink = 0;
75 var flag = 0;
76 var HttpGet = function(url,callback){
77 //10s timeout
78 var request_timer = setTimeout(function() {
79 req.abort();
80 console.log(‘Request Timeout.‘);
81 }, 10000);
82
83 var req = http.get(url, function(res) {
84 clearTimeout(request_timer);
85
86 res.on(‘data‘, function () {
87 }).on(‘end‘, function(){
88 console.log(++flag + ": " + url + ‘ response status: ‘ + res.statusCode);
89
90 if(!(res.statusCode >= 200 && res.statusCode < 400)){
91 console.log(‘-----------------------‘);
92 badLink++;
93 }
94
95 callback();
96 });
97 });
98 req.on(‘error‘, function(err){
99 console.log(++flag + ": " + ‘problem with request: ‘ + err.message);
100 badLink++;
101 callback();
102 });
103 };
104
105 var urls = filterUrl(matches,host);
106
107 if(urls !== null){
108 var totalLink = urls.length;
109 //console.log(urls);
110 async.eachSeries(urls, HttpGet, function(err){
111 // var urlBadLink = new UrlBadLink(host,totalLink, badLink);
112 // console.log("坏链个数为: " + urlBadLink.badCounts);
113 // console.log("坏链率为: " + urlBadLink.getRate());
114 urlBadLink.total = totalLink;
115 urlBadLink.badCounts = badLink;
116 //data store puts here
117 dbHandle.updateBadLink(urlBadLink);
118 callend();
119 });
120 }else{
121 console.log(‘no links found‘);
122 urlBadLink.total = 10;
123 urlBadLink.badCounts = 0;
124 dbHandle.updateBadLink(urlBadLink);
125 callend();
126 }
127 }
128
129 //正则取得href属性值
130 function URLFommat(strUrl,host){
131
132 var urlPatten = /href=[\‘\"]?([^\‘\"]*)[\‘\"]?/i;
133 var temp = urlPatten.exec(strUrl);
134
135 if(temp!= null){
136 var url = temp[0].substring(6,temp[0].length-1).trim();
137
138 if(url.indexOf("\"") != -1){
139 url = url.slice(url.indexOf("\"") + 1);
140 }
141
142 if(url.charAt(0) == "/"){
143 url = url.slice(1);
144 return host + url;
145 }else if((url.indexOf("http") == -1)&&
146 (url.indexOf("javascript") == -1)){
147 return host + url;
148 }else
149 return url;
150 }else
151 return null;
152 }
153
154 //
155 function URLFommat1(strUrl,host){
156
157 var urlPatten = /href=[\‘\"]?([^\‘\"]*)[\‘\"]?/i;
158 var temp = urlPatten.exec(strUrl);
159
160 if(temp!= null){
161 var url = temp[0].substring(6,temp[0].length-1).trim();
162
163 if(url.indexOf("\"") != -1)
164 url = url.slice(url.indexOf("\"") + 1);
165
166 if(url.charAt(0) == "/")
167 return "http://" + host + url;
168 else if((url.indexOf("http") == -1)&&
169 (url.indexOf("javascript") == -1)){
170 return "http://" + host+"/" + url;
171 }else
172 return url;
173 }else
174 return null;
175 }
176 //test URLFommat
177 //var test = "http://baidu.com";
178 // var test1 = " \"http://baidu.com";
179 //var test2 = "/wenhao";
180 //console.log(URLFommat(test,"www.sina.com.cn"));
181 //console.log(URLFommat(test1,"www.sina.com.cn"));
182 //console.log(URLFommat(test2,"www.sina.com.cn"));
183
184
185 //测试是否为常见url格式
186 function IsURL(strUrl) {
187 if(strUrl != null){
188 var regular = /^\b(((http?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|asia|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\@&?=+,.!\/~%\$]*)?)$/i;
189 if (regular.test(strUrl)) {
190 return true;
191 }
192 else {
193 return false;
194 }
195 }else
196 return false;
197 }
198
199
200 //对象
201 function UrlBadLink(id, host, total, badCounts){
202 this.id = id;
203 this.host = host;
204 this.total = total;
205 this.badCounts = badCounts;
206
207 if(typeof this.getRate != "function"){
208 UrlBadLink.prototype.getRate = function(){
209 var output = Number(Math.round(this.badCounts/this.total*10000)/100).toFixed(2)+‘%‘;
210 return output;
211 };
212 }
213 }
214
215 function filterUrl(arr,host){
216
217 if(arr === null)
218 return null;
219 var output = [];
220 arr.forEach(function(item,index,array){
221 //console.log(item);
222 var formatURL = URLFommat(item,host);
223
224 if(IsURL(formatURL)){
225 output.push(formatURL);
226 }//if
227 });//forEach
228
229 return output;
230 }

第二个文件:将数据存库,dbHandle.js


/**
* @author MissUU
* @des MySql基本操作
* API: https://github.com/felixge/node-mysql
*/

var mysql = require(‘mysql‘);

mysql.createConnection(‘mysql://root:[email protected]/test?debug=false‘);

var pool = mysql.createPool({
host : ‘10.102.1.00‘,
user : ‘root‘,
password : ‘root‘,
database : ‘test‘,
connectionLimit: 15
});

//读取urls
exports.showUrls = function (groupId, callback){

console.log(‘this is showUrl()‘);
pool.getConnection(function(err, conn){

if (err) {
console.log("connection error!");
console.log(err);
}

conn.query(‘SELECT id,realurl as url FROM t_site WHERE siteGroupId = ?‘,groupId, function(err, result){
if(err){
console.log(err.message);
}

conn.release();
if(result.length){
// console.log(result instanceof Array);
callback(result);
return true;
}else{
callback(‘‘);
return false;
}
});
});
};

exports.updateBadLink = function (urlBadLink){
//若不含数据则不插入
if (!!urlBadLink) {

pool.getConnection(function(err, conn){

if (err) {
console.log("connection error!");
console.log(err);
}

var updateSql = "UPDATE a_qualityinfo SET brokenRate = ‘"+ urlBadLink.getRate() +"‘ WHERE siteId = " + urlBadLink.id;

console.log(updateSql);

conn.query(updateSql, function(err, result){
if(err){
console.log(err.message);
console.log(‘update fail‘);
}

conn.release();
console.log(‘update success‘);
});// conn.query
});//pool.getConnection
}
};

代码后期还会改动,这里有几点需要注意的:

1、http.get有时会一直等待响应,所以一定要判断下,超时则认为出错,要不程序就卡住了。。。= =!

2、注意callback的使用,要不然很难规范执行顺序的,用过nodejs的都懂得。。。

时间: 2024-10-13 22:22:58

nodejs写的一个网页爬虫例子(坏链率)的相关文章

如何写好一个网页---传智首页

---恢复内容开始--- 学习前端知识也有一个月了吧,十月十四号来到这里学习的,一直到11月7号,差不多也有一个月的时间了,所以今天想谢谢这个时间段学到的一些知识,也留着以后能够回头看看这段时间的付出. 今天写的主题内容是一个简单的网页制作,用的模板的话就是传智的首页,因为自己素材只有传智首页的素材罢了... 对我而言,想要去设计一个网站,我先会做大量的分析,第一步做的就是对整个网站的整体框架的和模块的划分.就例如传智首页来说,我选择将这个首页看成是一个最大的整体模块,然后在这个模块里面去再划分

因为业务需要,用nodejs写了一个css解析器,因为是基础库,想开源,不知道有没有人需要。

一般而言htmlparser的解析使用得比较多,node库中已经有了,npm install -g htmlparser2就可以安装. 这段时间要实现nodejs上的安全扫描,需要对html,css,js进行解析,css主要是限制一些绝对定位,浮层和url,防止产生钓鱼或攻击.所以写了一个css的解析器. 感觉 这些基础库应该公开出去,但是不知道有多少人有这个需求.

Java学习笔记——面试常客:写出一个死锁的例子

现在的面试挺蛋疼,为了考察大家的语言掌握水平,类似这样的题特别多,不过在某个角度来说确实能看出一个人对某个知识点的理解,就比如今天这个死锁的小例子,主要考察大家对线程死锁概念的理解程度,也考察大家对java语言的敲代码水平,下面是一个死锁的简单例子: <span style="font-size:18px;">class Test implements Runnable { private boolean flag; //flag标签,让t1和t2线程执行不同代码 publ

自己写的一个依赖注入例子

首先有一个Book基类,里面有一个content方法 然后有2本书 MathBook 和 EnglishBook ,继承Book接口 然后有一个教师基类Teacher,里面有一个Teach方法,Teach方法依赖于Book类 然后有2名教师,男老师manTeacher 和 女老师womanTeacher,继承Teacher接口 Debug.Log( "男老师教" + book.content()); Debug.Log("女老师教" + book.content()

网页抓取:PHP实现网页爬虫方式小结

来源:http://www.ido321.com/1158.html 抓取某一个网页中的内容,需要对DOM树进行解析,找到指定节点后,再抓取我们需要的内容,过程有点繁琐.LZ总结了几种常用的.易于实现的网页抓取方式,如果熟悉JQuery选择器,这几种框架会相当简单. 一.Ganon 项目地址: http://code.google.com/p/ganon/ 文档: http://code.google.com/p/ganon/w/list 测试:抓取我的网站首页所有class属性值是focus的

网页爬虫的设计与实现(Java版)

网页爬虫的设计与实现(Java版)     最近为了练手而且对网页爬虫也挺感兴趣,决定自己写一个网页爬虫程序. 首先看看爬虫都应该有哪些功能. 内容来自(http://www.ibm.com/developerworks/cn/java/j-lo-dyse1/index.html?ca=drs-) 网页收集的过程如同图的遍历,其中网页就作为图中的节点,而网页中的超链接则作为图中的边,通过某网页的超链接 得到其他网页的地址,从而可以进一步的进行网页收集:图的遍历分为广度优先和深度优先两种方法,网页

c#网页爬虫初探

一个简单的网页爬虫例子! html代码: <head runat="server"> <title>c#爬网</title> </head> <body> <form id="form1" runat="server"> <div style="margin:0 auto;width:700px"> <asp:TextBox ID=&qu

一个单元测试的例子

代码中引入单元测试,理论上是正确的,但是还没有实践过.但是从产品的角度去考虑的话,单元测试的必要性是很高的,"重构"这个东西听了好多,但是在公司内部,敢做重构的人估计不多,我曾经做过小功能的重构,那也是在比较熟悉这个功能的基础上做得,但是对于不规范.逻辑混乱的代码,估计就没人敢动手了,所以对于重构,其实是需要手段保证的,单元测试不能完全保证代码的各个层面重构,但是一定程度上是可以起到作用的. 基于上面的考虑,我考虑对service层做单元测试,起码保证服务层是有重构的空间. 从零开始研

一次使用NodeJS实现网页爬虫记

前言 几个月之前,有同事找我要PHP CI框架写的OA系统.他跟我说,他需要学习PHP CI框架,我建议他学习大牛写的国产优秀框架QeePHP. 我上QeePHP官网,发现官方网站打不开了,GOOGLE了一番,发现QeePHP框架已经没人维护了.API文档资料都没有了,那可怎么办? 毕竟QeePHP学习成本挺高的.GOOGLE时,我发现已经有人把文档整理好,放在自己的个人网站上了.我在想:万一放文档的个人站点也挂了, 怎么办?还是保存到自己的电脑上比较保险.于是就想着用NodeJS写个爬虫抓取需