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

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

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

 /*================================================
@author MissUU
链接抓取思路: 1. 获取页面内容
2. 正则取得所有<a>
3. 进一步取得href属性值,如果首位是“则剔除,不是http开头加上域名(javascript开头除外)
4.正则验证是否是常见URL格式
================================================*/
var http = require('http');
var async = require('async');
var dbHandle = require('./dbHandle.js'); //主程序
var runUrlSpider = function(obj, callback){
//10s timeout
var request_timer = setTimeout(function() {
req.abort();
console.log('Request Timeout.');
}, 10000); var urlBadLink = new UrlBadLink();
var html='';
var req = http.get(obj.url, function(res) { clearTimeout(request_timer); res.setEncoding('utf8');
res.on('data', function (chunk) {
html += chunk;
}).on('end', function(){
console.log('*******开始提取有效链接地址******');
console.log(new Date().toLocaleString());
console.log(obj.url);
urlBadLink.host = obj.url;
urlBadLink.id = obj.id;
matchURL(html, urlBadLink, function(){
callback();
});
});
}); req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback();
});
} //this is the entrance of code
var main = function(){
var urlArray = dbHandle.showUrls(1, function(result){
async.eachSeries(result, runUrlSpider, function(err){
console.log('******this is the end, haha*******');
});
});
// console.log(urlArray); }; main(); /*
* 用于异步放送get请求
*
* @param {string} content 原始页面信息
* @param {string} host 主域名
*/
function matchURL(content, urlBadLink, callend){
var host = urlBadLink.host;
var anchor = /<a\s[^>]*>/g;
var matches = content.match(anchor);
var badLink = 0;
var flag = 0;
var HttpGet = function(url,callback){
//10s timeout
var request_timer = setTimeout(function() {
req.abort();
console.log('Request Timeout.');
}, 10000); var req = http.get(url, function(res) {
clearTimeout(request_timer); res.on('data', function () {
}).on('end', function(){
console.log(++flag + ": " + url + ' response status: ' + res.statusCode); if(!(res.statusCode >= 200 && res.statusCode < 400)){
console.log('-----------------------');
badLink++;
} callback();
});
});
req.on('error', function(err){
console.log(++flag + ": " + 'problem with request: ' + err.message);
badLink++;
callback();
});
}; var urls = filterUrl(matches,host); if(urls !== null){
var totalLink = urls.length;
//console.log(urls);
async.eachSeries(urls, HttpGet, function(err){
// var urlBadLink = new UrlBadLink(host,totalLink, badLink);
// console.log("坏链个数为: " + urlBadLink.badCounts);
// console.log("坏链率为: " + urlBadLink.getRate());
urlBadLink.total = totalLink;
urlBadLink.badCounts = badLink;
//data store puts here
dbHandle.updateBadLink(urlBadLink);
callend();
});
}else{
console.log('no links found');
urlBadLink.total = 10;
urlBadLink.badCounts = 0;
dbHandle.updateBadLink(urlBadLink);
callend();
}
} //正则取得href属性值
function URLFommat(strUrl,host){ var urlPatten = /href=[\'\"]?([^\'\"]*)[\'\"]?/i;
var temp = urlPatten.exec(strUrl); if(temp!= null){
var url = temp[0].substring(6,temp[0].length-1).trim(); if(url.indexOf("\"") != -1){
url = url.slice(url.indexOf("\"") + 1);
} if(url.charAt(0) == "/"){
url = url.slice(1);
return host + url;
}else if((url.indexOf("http") == -1)&&
(url.indexOf("javascript") == -1)){
return host + url;
}else
return url;
}else
return null;
} //test URLFommat
//var test = "http://baidu.com";
// var test1 = " \"http://baidu.com";
//var test2 = "/wenhao";
//console.log(URLFommat(test,"www.sina.com.cn"));
//console.log(URLFommat(test1,"www.sina.com.cn"));
//console.log(URLFommat(test2,"www.sina.com.cn")); //测试是否为常见url格式
function IsURL(strUrl) {
if(strUrl != null){
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;
if (regular.test(strUrl)) {
return true;
}
else {
return false;
}
}else
return false;
} //对象
function UrlBadLink(id, host, total, badCounts){
this.id = id;
this.host = host;
this.total = total;
this.badCounts = badCounts; if(typeof this.getRate != "function"){
UrlBadLink.prototype.getRate = function(){
var output = Number(Math.round(this.badCounts/this.total*10000)/100).toFixed(2)+'%';
return output;
};
}
} function filterUrl(arr,host){ if(arr === null)
return null;
var output = [];
arr.forEach(function(item,index,array){
//console.log(item);
var formatURL = URLFommat(item,host); if(IsURL(formatURL)){
output.push(formatURL);
}//if
});//forEach return output;
}

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

/**
* @author MissUU
* @des MySql基本操作
* API: https://github.com/felixge/node-mysql
*/ var mysql = require('mysql'); mysql.createConnection('mysql://root:apple@localhost/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的都懂得。。。

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

  1. 用go iris 写的一个网页版文件共享应用(webapp)

    主要演示文件拖拽上传或点击上传到不同的目录中,提供下载和删除功能. 目录结构: -main.go --share(用于分类存放上传文件的目录) --v(视图目录) ---share.html main ...

  2. 用Python写一个小爬虫吧!

    学习了一段时间的web前端,感觉有点看不清前进的方向,于是就写了一个小爬虫,爬了51job上前端相关的岗位,看看招聘方对技术方面的需求,再有针对性的学习. 我在此之前接触过Python,也写过一些小脚 ...

  3. Jmeter_ForEach控制器实现网页爬虫

    一直以来,爬虫似乎都是写代码去实现的,今天像大家介绍一下Jmeter如何实现一个网页爬虫! Jmeter的爬虫原理其实很简单,就是对网页提交一个请求,然后把返回的所有href提取出来,利用ForEac ...

  4. Jmeter(十九)_ForEach控制器实现网页爬虫

    一直以来,爬虫似乎都是写代码去实现的,今天像大家介绍一下Jmeter如何实现一个网页爬虫! 龙渊阁测试开发家园 317765580 Jmeter的爬虫原理其实很简单,就是对网页提交一个请求,然后把返回 ...

  5. c#网页爬虫初探

    一个简单的网页爬虫例子! html代码: <head runat="server"> <title>c#爬网</title> </head ...

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

    网页爬虫的设计与实现(Java版)     最近为了练手而且对网页爬虫也挺感兴趣,决定自己写一个网页爬虫程序. 首先看看爬虫都应该有哪些功能. 内容来自(http://www.ibm.com/deve ...

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

    来源:http://www.ido321.com/1158.html 抓取某一个网页中的内容,需要对DOM树进行解析,找到指定节点后,再抓取我们需要的内容,过程有点繁琐.LZ总结了几种常用的.易于实现 ...

  8. Python网页爬虫(一)

    很多时候我们想要获得网站的数据,但是网站并没有提供相应的API调用,这时候应该怎么办呢?还有的时候我们需要模拟人的一些行为,例如点击网页上的按钮等,又有什么好的解决方法吗?这些正是python和网页爬 ...

  9. PHP实现网页爬虫

    抓取某一个网页中的内容,需要对DOM树进行解析,找到指定节点后,再抓取我们需要的内容,过程有点繁琐.LZ总结了几种常用的.易于实现的网页抓取方式,如果熟悉JQuery选择器,这几种框架会相当简单. 一 ...

随机推荐

  1. Photoshop CS4序列号过期的问题

    1)在网络上搜寻一些PS CS4序列号: 如1330-1221-6824-4838-0308-6823,1330-1283-7461-4574-7002-2504,1330-1795-2880-537 ...

  2. NPOI操作EXCEL----------NPOI基础01

    来源地址:http://www.cnblogs.com/csqb-511612371/p/4878059.html 先来介绍一下NPOI基本的东西: 1.下载地址:http://npoi.codepl ...

  3. Intellij IDEA采用Maven+Spring MVC+Hibernate的架构搭建一个java web项目

    原文:Java web 项目搭建 Java web 项目搭建 简介 在上一节java web环境搭建中,我们配置了开发java web项目最基本的环境,现在我们将采用Spring MVC+Spring ...

  4. C++:常类型Const

    常类型:使用类型修饰符const说明的类型,常类型的变量或对象成员的值在程序运行期间是不可改变的. 3.10.1 常引用 如果在说明引用时用const修饰,则被说明的引用为常引用.如果用常引用做形参, ...

  5. trim合理和谐

    今天早上,到公司,噩耗传来.上周的上线的功能出现问题,后台mis中有数据不能保存了. 经过紧张的查找,还是我的问题.有一个查重操作,在查重前,会比对新旧值,新值顺手trim了.旧值直接保存了. 在比较 ...

  6. C# 写入XML文档三种方法详细介绍

      三个类将同样的xml内容写入文档,介绍了如何使用XmlDocument类对XML进行操作,以及如何使用LINQ to XML对XML进行操作. 它们分别使用了XmlDocument类和XDocum ...

  7. 8天学通MongoDB——第四天 索引操作

    这些天项目改版,时间比较紧,博客也就没跟得上,还望大家见谅. 好,今天分享下mongodb中关于索引的基本操作,我们日常做开发都避免不了要对程序进行性能优化,而程序的操作无非就是CURD,通常我们 又 ...

  8. 函数 xdes_get_descriptor_with_space_hdr

    获得区描述符 xdes entry 的offset /********************************************************************//** ...

  9. 关于post get ajax

    今天写程序时  出现了下面问题: 前台 $.post('ajax/GetDataAjax.ashx', { 'mode': 'DEL', 'BM_ID': bm_id }, function (res ...

  10. BZOJ2626: JZPFAR

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2626 题解:裸K-Dtree,最大值?自己yy一下估价函数就好了. 两题居然是同一个错误,真是 ...