因为工作需要,用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. jdbc的通讯录CRUD

    基于JDBC的通讯录练手:项目以MVC模式开发,包名:cn.itcast.txl.domain;cn.itcast.txl.dao;cn.itcast.txl.dao.impl;cn.itcast.t ...

  2. MIT算法导论——第五讲.Linear Time Sort

    本栏目(Algorithms)下MIT算法导论专题是个人对网易公开课MIT算法导论的学习心得与笔记.所有内容均来自MIT公开课Introduction to Algorithms中Charles E. ...

  3. Java多线程2:实现多线程的两种方式

    原文:http://www.cnblogs.com/skywang12345/p/3479063.html 常见的实现多线程的方式有2种,一是继承Thread类,二是实现 Runnable接口,还可以 ...

  4. Spring Data JPA教程, 第三部分: Custom Queries with Query Methods(翻译)

    在本人的Spring Data JPA教程的第二部分描述了如何用Spring Data JPA创建一个简单的CRUD应用,本博文将描述如何在Spring Data JPA中使用query方法创建自定义 ...

  5. SQLserver游标原理和使用方法

    在数据库开发过程中,当你检索的数据只是一条记录时,你所编写的事务语句代码往往使用SELECT INSERT 语句.但是我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记录.那么如何解决这种问题呢 ...

  6. BootStrap弹窗

    效果图: 注意引入的文件,js文件要在前面 Bootstrap框架中的模态弹出框,分别运用了“modal”.“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在 ...

  7. UVa 10735 (混合图的欧拉回路) Euler Circuit

    题意: 给出一个图,有的边是有向边,有的是无向边.试找出一条欧拉回路. 分析: 按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边. 但是在这里却行不通了,因为拆成两条有向边的话, ...

  8. createElement 创建DOM元素

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  9. 简单分析什么是SQL注入漏洞

    现在很多人在入侵的过程中基本都是通过SQL注入来完成的,但是有多少人知道为什么会有这样的注入漏洞呢?有的会随口说着对于字符的过滤不严造成的.但是事实是这样吗?我们学这些,不仅要知其然,更要知其所以然! ...

  10. ios9下ionic框架报[$rootScope:infdig] 10 $digest() iterations reached. Aborting!的解决办法

    升级ios9后,ionic开发的app会报[$rootScope:infdig] 10 $digest() iterations reached. Aborting!的错误,加上一个patch就可以解 ...