学习笔记
前言
近期做一个数据抓爬工具,最开始使用的是C#控制台应用,同时正则表达式去过滤数据,看着还行,可每次运行都依附于.net framework很是不爽,于是想整点其他的方法。本人还是比较喜欢javascript的,思来想去决定用服务器端的javascript来试试!
环境、工具准备
1、[必装] 安装nodejs,下载最新nodejs,点击此处
2、[选装] 安装iisnode,以及rewrite,因为我是以IIS作为Server,所以用到了这2个IIS的拓展插件,假如仅仅只是cmd控制台运行node则这第二项忽略
3、附加信息:当安装成功之后,在IIS下回出现URL重写这么个东东
范例实现
我以一个小小的案例来实现这么个功能,咱们去抓下面这个站点的数据测试一下:http://www.jj59.com/
1、抓列表,http://www.jj59.com/jingpinwenzhang/list_68_3.html
2、抓详情,http://www.jj59.com/jingpinwenzhang/082919.html
原网站截图如下:
接下来我要做的就是
1、将指定页的列表页中文章的标题与对应链接过滤出来,然后返回json数组
2、将详情页文章标题,作者,创建时间,内容过滤出来,然后返回json对象
具体nodejs代码于运行结果
1 var http = require('http'); 2 var _url = require('url'); //引用url模块,处理url地址相关操作 3 var cheerio = require("cheerio"); //引用cheerio模块,使在服务器端像在客户端上操作DOM,不用正则表达式 4 var iconv = require('iconv-lite'); //解决编码转换模块 5 var BufferHelper = require('bufferhelper'); //关于Buffer我后面细说 6 /* 7 *最后我需要达到的效果是,给予一个访问地址,形如:http://www.mynode.com?link=www.abc.com&callback=cb 8 *我希望可以返回json,也可返回jsonp 9 */ 10 11 http.createServer(function (req, res) { 12 var arg = _url.parse(req.url, true).query; //通过调用url模块,获取查询字符串参数集合 13 var link = arg.link; //获取抓取的link 14 var callback = arg.callback; //回调函数的名称 15 //若没有对link加上http,则补全 16 var protocol = "http"; 17 if (link.indexOf("http") < 0) { 18 link = protocol + "://" + link; 19 } 20 //抓取页面 21 download(link, function (data) { 22 res.writeHead(200, { 23 "Content-Type": "text/html;charset=utf-8", 24 "Transfer-Encoding": "chunked" 25 }); 26 var doc = data.toString(); 27 var $ = cheerio.load(doc); 28 var list = []; 29 $(".e2 li .title").each(function (i, e) { 30 var item = $(e).children("a").last(); 31 var title = item.text(); 32 var link = item.attr("href"); 33 list.push({ "title": title, "link": link }); 34 }); 35 var jsonText = JSON.stringify(list); 36 if (callback) { 37 res.write(callback + "(" + jsonText + ")"); 38 } 39 else { 40 res.write(jsonText); 41 } 42 res.end(); 43 }); 44 }).listen(process.env.PORT); 45 46 //加载第三方页面 47 function download(url, callback) { 48 http.get(url, function (res) { 49 var bufferHelper = new BufferHelper(); //解决中文编码问题 50 res.on('data', function (chunk) { 51 bufferHelper.concat(chunk); 52 }); 53 res.on("end", function () { 54 //注意,此编码必须与抓取页面的编码一致,否则会出现乱码,也可以动态去识别 55 var val = iconv.decode(bufferHelper.toBuffer(), 'gb2312'); 56 callback(val); 57 }); 58 }).on("error", function () { 59 callback(null); 60 }); 61 }