使用node的http模块实现爬虫功能,并把爬到的数据存入mongondb
刚开始使用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;
使用node的http模块实现爬虫功能,并把爬到的数据存入mongondb的更多相关文章
- python爬虫Scrapy(一)-我爬了boss数据
一.概述 学习python有一段时间了,最近了解了下Python的入门爬虫框架Scrapy,参考了文章Python爬虫框架Scrapy入门.本篇文章属于初学经验记录,比较简单,适合刚学习爬虫的小伙伴. ...
- 【网络爬虫】【java】微博爬虫(一):小试牛刀——网易微博爬虫(自定义关键字爬取微博数据)(附软件源码)
一.写在前面 (本专栏分为"java版微博爬虫"和"python版网络爬虫"两个项目,系列里所有文章将基于这两个项目讲解,项目完整源码已经整理到我的Github ...
- 【python网络编程】新浪爬虫:关键词搜索爬取微博数据
上学期参加了一个大数据比赛,需要抓取大量数据,于是我从新浪微博下手,本来准备使用新浪的API的,无奈新浪并没有开放关键字搜索的API,所以只能用爬虫来获取了.幸运的是,新浪提供了一个高级搜索功能,为我 ...
- python网络爬虫抓取动态网页并将数据存入数据库MySQL
简述以下的代码是使用python实现的网络爬虫,抓取动态网页 http://hb.qq.com/baoliao/ .此网页中的最新.精华下面的内容是由JavaScript动态生成的.审查网页元素与网页 ...
- Scrapy爬虫入门系列3 将抓取到的数据存入数据库与验证数据有效性
抓取到的item 会被发送到Item Pipeline进行处理 Item Pipeline常用于 cleansing HTML data validating scraped data (checki ...
- python网络爬虫(7)爬取静态数据详解
目的 爬取http://seputu.com/数据并存储csv文件 导入库 lxml用于解析解析网页HTML等源码,提取数据.一些参考:https://www.cnblogs.com/zhangxin ...
- Python使用Scrapy框架爬取数据存入CSV文件(Python爬虫实战4)
1. Scrapy框架 Scrapy是python下实现爬虫功能的框架,能够将数据解析.数据处理.数据存储合为一体功能的爬虫框架. 2. Scrapy安装 1. 安装依赖包 yum install g ...
- 爬虫从网页中去取的数据中包含 空格
爬虫从网页中爬取的数据中带了一个 这样的空格,使用trim()函数和replace(" ", "")去掉不了,找了一下资料发现,空格有两种一种是从键盘输入的对应 ...
- 今天用node的cheerio模块做了个某乎的爬虫
一时兴起,想做个爬虫,经过各种深思熟虑,最后选择了某乎,毕竟现在某乎的数据质量还是挺高的.说干就干 打开某乎首页,随便搜索了一串关键字,相关的问题和答案就展现在眼前,我就思考怎么把这些搜索结果 ...
随机推荐
- DOS删除服务
启动服务: net start 服务名 停止服务: net stop 服务名 卸载服务: 服务名 -uninstall 安装服务:sc create ser ...
- OpenGL1-6讲小结
首先是第一讲,GL窗体的搭建,依葫芦画瓢,很多代码虽然解释了,最后看起来还是比较生涩.一开始按照上一篇的链接去敲的代码,结果最后while死循环了,我也不知道问题出哪儿,后来去找了个源码,还附带了更加 ...
- C++ 双链表基本操作
上一篇博客主要总结了单向链表,这次再总结一下双向链表. 1.概念 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都 ...
- int * const 与 const int * 的区别
type * const 与 const type * 是在C/C++编程中特别容易混淆的两个知识点,现在就以 int * const 和 const int * 为例来简略介绍一下这两者之间的区别. ...
- C# http下载(支持断点续传)
分享下项目里面自己封装的一个http下载类 功能如下: 1.支持断点续传 2.下载失败自动重试 3.超时等异常处理 using System; using System.Collections.Gen ...
- Window Phone 8开发问题反思
项目开发有段时间了,进入了阶段测试.然而在测试过程中bug连连不断,在抱怨产品需求的坑爹.不合理之外,我也一直在反思为什么会出现这么多Bug. 首先,由于项目开发的两个人都是新手,在刚刚认识MVVM架 ...
- jQuery: 图片不完全按比例自动缩小
有时我们会有这样的需求:让图片显示在固定大小的区域.如果不考虑 IE6 完全可以使用 css 的 max-width 限制宽度自动按比例缩小显示,但是这样有个问题,就是如果按比例缩小后,图片高度不够, ...
- NSS_10 EXTJS给弹出的子窗口传递参数
在桌面程序中, 如果需要弹出一个子面板, 并且需要传一些参数给子面板, 我通常的作法就是:在子面板添加对应的数据成员,然后一个构造函数来接收这些参数并赋值级数据成员. 实现起来非常方便. 但是在Ext ...
- WCF 服务的ABC之契约(七)
契约 Contract WCF的所有服务都会公开为契约(Contract),契约与平台无关,是描述服务功能的标注方式. 服务契约(Service Contract) 服务契约描述的是一个服务,它定义了 ...
- Winform webBrowser 不跳转网页
private void webBrowser1_NewWindow(object sender, CancelEventArgs e) { string url = ((WebBrowser)sen ...