刚开始使用http中间件做爬虫其实蛮多坑的,最主要的坑就是编码问题,有很多中文网站的采用的gb2313的编码方式,这个在爬到的报文解析就很蛋碎,
因为http中间件对utf-8支持的比较好,所以针对这一点我们需要对于gb2312的网站做编码转换处理
这里我使用了mongoose,所以node执行js会先链接test数据库
这里爬了百度阅读的数据,但是爬下来的图片链接在本地网页是不能使用的,百度图片服务器做了请求筛选
代码如下:
/** * Created by Myco on 2016/3/15. */ /* * iconv-lite 模块能配合 http 模块以及 request 模块使用,却不能直接和 superAgent 模块使用。 * 因为 superAgent 是以 utf8 去取数据,然后再用 iconv 转也是不行的。 * 页面是 gbk 编码的,sres.text 已经是 decode 过了的结果, * 也就是说它已经被转换成 utf8 了,再转换成 buffer 出来的结果必须是不正确的。 */ var http = require(‘http‘); //提供jquery的功能进行dom节点操作 var cheerio = require(‘cheerio‘); var mongoose = require(‘mongoose‘); //纯Javascript转换编码的模块 iconv-lite var iconv = require(‘iconv-lite‘); //bufferhelper是一个操作buffer的加强类 var Bufferhelper =require(‘bufferhelper‘); //当前为mongon的表结构实例对象 var BookModel = require(‘../models/model/bookModel‘); //创建一个数据库连接 mongoose.connect(‘mongodb://localhost/test‘); //设置访问地址,百度是gb2312编码的数据,所以必须使用iconv.decode var url = ‘http://yuedu.baidu.com/‘ http.get(url,function(res){ var bufferhelper =new Bufferhelper(); res.on(‘data‘,function(data){ //返回的都是Buffer数据 console.log(‘------------下载中‘+Buffer.isBuffer(data)+‘-------------‘); bufferhelper.concat(data); }); res.on(‘end‘,function(){ console.log(‘------------结束-------------‘); var html = iconv.decode(bufferhelper.toBuffer(),‘GBK‘); filtehtml(html); }); }).on(‘error‘,function(){ console.log(‘获取数据失败!‘); }) //html文档过滤出有效信息 function filtehtml(html){ //cheerio本身默认是转实体的,所以保证转换成功必须加参数{decodeEntities: false},和编码无关 var $ = cheerio.load(html,{decodeEntities: false}); var collist= $(‘.yd-reco-wrap‘); console.log(‘------------数据收集-------------‘); console.log(‘------------collist数据长度:‘+collist.length+‘-------------‘); var data = []; for(var i= 0,l=collist.length;i<l;i++){ var docObj= $(collist[i]); var item = {}; item.bookColName = docObj.find(‘.mod-title‘).text(); item.categoryId = 999999; var listObj = docObj.find(‘.book‘); var booklist = []; for(var q= 0,ql=listObj.length;q<ql;q++){ var bookObj = $(listObj[q]); var bookData = {}; bookData.title = bookObj.find(‘.book-title‘).text(); bookData.currentPrice = bookObj.find(‘.book-price‘).text().replace(‘¥‘,‘‘); bookData.src = bookObj.find(‘.book-cover .book-img‘)[0].attribs[‘data-src‘]; bookData.author = bookObj.find(‘.book-card-author‘).text(); var url = bookObj.find(‘.book-card-wrap‘)[0].attribs.href; if(url){ bookData.id = url.replace(/\/ebook\/|\?fr=index/g,‘‘); bookData.url = url; } add(bookData); booklist.push(bookData); } item.booklist = booklist; data.push(item); } } function add(bookData){ if(bookData.url){ http.get(‘http://yuedu.baidu.com/‘+bookData.url,function(res){ var bufferhelper =new Bufferhelper(); res.on(‘data‘,function(data){ bufferhelper.concat(data); }); res.on(‘end‘,function(){var html = iconv.decode(bufferhelper.toBuffer(),‘GBK‘); console.log(html); var $ = cheerio.load(html,{decodeEntities: false}); var content = $(‘#bd .main .scaling-content p‘).text(); console.log(content); }); }).on(‘error‘,function(){ console.log(‘获取数据失败!‘); }) } }
bookModel.js文件如下,实例化了mongondb表结构,并为表取名book(代码中引入了bookSchema.js文件,若使用如下代码,请注意js文件路径)
var mongoose = require(‘mongoose‘); var bookSchema = require(‘../schema/bookSchema.js‘); //指定数据库表名称为book var BookModel = mongoose.model(‘book‘,bookSchema,‘book‘); module.exports = BookModel;
bookSchema.js 文件如下,主要是Schema定义mongondb的数据表结构和默认值
var mongoose = require(‘mongoose‘); var bookSchema = new mongoose.Schema({ id:String, src:String,//图片地址 title:{type:String,required:true},//书名,添加姓名非空约束 content:String,//内容 author:String,//作者 rq:{type:Number,default:0},//阅读量 price:{type:Number,min:0,max:1000},//价格,添加价格约束 isShow:{type:Boolean,default:true},//约束是否显示 classify:{type:String,enum:[‘青春‘,‘文学‘,‘历史‘,‘科幻‘,‘小说‘,‘言情‘,‘军事‘],default:‘青春‘},//类型,枚举限定类型 currentPrice:{type:Number,default:0},//当前售价 comments_count:{type:Number,default:0},//评论数 meta:{//object类型时间对象 createDate:{ type:Date, default:Date.now() }, updateDate:{ type:Date, default:Date.now() } } },{versionKey:false}); module.exports = bookSchema;
时间: 2024-10-14 06:37:01