demo截图:

本demo爬瓜子二手车北京区的数据 (注:需要略懂 node.js / mongodb 不懂也没关系 因为我也不懂啊~~~)

之所以选择爬瓜子二手车网站有两点:

一、网站无需登录,少做模拟登录;

二、数据链接没有加密,直接可以用;

网上很多node.js爬虫的栗子

但大多是一个页面的栗子,很少跟数据库结合的 所以我这个栗子是糖炒的

我的基本思路是这样的

1、先在mongodb里存所有页的链接地址的集合

2、在根据这些链接地址 一个一个的把详细信息爬下来

第一步在搜索页找到翻页的规律

像搜索页北京区第一页就是

https://www.guazi.com/bj/buy/o1/

第二页

https://www.guazi.com/bj/buy/o2/

规律就是

https://www.guazi.com/bj/buy/o + number

然后第一页的时候你就可以知道最多50页

这样你就可以循环这些链接在把每个页面的车的详情链接存到mongodb的集合里

第二步读mongodb的集合找出所有的链接 循环链接爬详情页数据

项目目录:

目录讲解:

reptile.js      //爬所有链接的;

carinfo.js     //爬车辆详情页;

package.json  //配置文件

package.json:

 {
"name": "sell-car",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cheerio": "^0.22.0",
"mongoose": "^4.7.1"
}
}

reptile.js 存mongodb集合   在cmd执行的 node reptile.js

 'use strict';
var http = require('https'); //node https 模块;
var cheerio = require('cheerio'); //解析html模块;
var mongoose = require('mongoose'); //操作mongodb数据库模块;
mongoose.connect('mongodb://localhost/car'); //链接数据库; var num = 0; //当前第几页;
var maxNum = 0; //最大页数; var url = 'https://www.guazi.com/bj/buy/o'; //瓜子二手车搜索页北京区; var PersonSchema = new mongoose.Schema({ //json的结构;
address:String //定义一个属性name,类型为String
}); var sellCar = mongoose.model('sell_car', PersonSchema ); //创建model fetchPage(url+1); //主程序开始运行 function fetchPage(x) { //封装了一层函数
startRequest(x);
} function startRequest(x) {
//采用http模块向服务器发起一次get请求
http.get(x, function (res) { var html = ''; //用来存储请求网页的整个html内容
var titles = [];
res.setEncoding('utf-8'); //防止中文乱码
//监听data事件,每次取一块数据
res.on('data', function (chunk) { html += chunk; }); //监听end事件,如果整个网页内容的html都获取完毕,就执行回调函数
res.on('end', function () { var $ = cheerio.load(html); //采用cheerio模块解析html var $a_src = $('.imgtype'); //读取出当前搜索页每辆车详情的地址; $a_src.each(function(i,obj){ //循环每地址链接存入数据库; var _src = $(obj).attr('href'); var carHref = new sellCar({ address: _src }); //存入mongodb;
carHref.save(function (err) {
if (err) {
console.log(err);
}
}); }) num++; //页码增加; if( num == 1 ){ //判断是第一次,给最大页数赋值;
maxNum = $('.pageLink li').eq($('.pageLink li').length-2).find('span').text();
} if( num == maxNum ){ //页数等于最大页数等值程序;
return ;
} fetchPage(url+num); }); });
}

carinfo.js 车辆详情 在cmd执行 node  carinfo.js

 'use strict';
var http = require('https'); //node https 模块;
var cheerio = require('cheerio'); //解析html模块;
var mongoose = require('mongoose'); //操作mongodb数据库模块;
mongoose.connect('mongodb://localhost/car'); //链接数据库; var readCarPer = new mongoose.Schema({ //json的结构;
address:String
}); var PersonSchema = new mongoose.Schema({ //定义json类型;
info:String, //车;
money:String, //价钱;
phone:String, //电话号码;
time:String, //上牌时间;
mileage:String, //公里数;
gearbox:String, //变速箱;
emission:String, //排放标准;
location:String, //上牌地;
imgs:Array //图片;
}); var num = 0;
var readCar = mongoose.model('sell_cars',readCarPer);
var sellCarInfo = mongoose.model('sell_carInfo', PersonSchema ); var json = null;
var url = 'https://www.guazi.com'; //补链接前边的链接;
var time = null; //间隔时间;
var maxNum = 0; readCar.find({},function(err, character){ //查找数据; console.log('成功读取地址'); if(err){
console.log(err);
}else{
json = character;
maxNum = json.length; calls(); } }) function calls(){
num++;
if( num > maxNum ){ //判断是否霸区成功;
console.log('数据爬去完成~~~');
return false;
} clearTimeout(time);
var lu = json[num].address; time = setTimeout(function(){ fetchPage(url+lu); //主程序开始运行 },5000); } function fetchPage(x) { //封装了一层函数
startRequest(x);
} function startRequest(x) {
console.log(x);
//采用http模块向服务器发起一次get请求
http.get(x, function (res) { var html = ''; //用来存储请求网页的整个html内容
var titles = [];
res.setEncoding('utf-8'); //防止中文乱码
//监听data事件,每次取一块数据
res.on('data', function (chunk) { html += chunk; }); //监听end事件,如果整个网页内容的html都获取完毕,就执行回调函数
res.on('end', function () { var $ = cheerio.load(html); //采用cheerio模块解析html var info = $('.dt-titletype').text() //车名;
var money = $('.numtype').text(); //钱;
var phone = $('.teltype').eq(0).text(); //电话
var time = $('.assort li').eq(0).find('b').text(); //上牌时间
var mileage = $('.assort li').eq(1).find('b').text(); //里程数
var gearbox = $('.assort li').eq(2).find('b').text(); //变速箱
var emission = $('.assort li').eq(3).find('b').text(); //排放标准
var location = $('.assort li').eq(4).find('b').text(); //上牌地 var $imgs = $('.dt-pictype img');
var imgs = []; $imgs.each(function(i,obj){ //图片循环赋值;
var img_src = $(obj).attr('data-original');
imgs.push(img_src);
}); var carInfos = new sellCarInfo({ //保存数据;
info:info,
money:money,
phone:phone,
time:time,
mileage:mileage,
gearbox:gearbox,
emission:emission,
location:location,
imgs:imgs
}); carInfos.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('成功数据!~~~');
calls();
}
}); }); });

当时爬数据的截屏:

后记:

这里我没说 mongodb 安装、启动、设置存储地址 是因为 mongodb本身在window和mac其实是不一样的所以需要你自己在找找别的文章看看怎么配置(注:window跑真的挺蛋疼的。。。。欢迎去感受一下)

这个栗子的第一个条件就是你要现在cmd里跑起来mongodb 要不剩下的都是白瞎

简单的mongodb的增删改查看看 菜鸟教程 就行 实在不行用Robomongo图形界面也行

说一个小问题

就是我在爬搜索的车辆链接的时候 因为下一页设置的间隔时间比较短 原本2000条的数据最后只爬下来1160,所以爬车辆详情的时候把间隔调成了5秒 需要注意一下;

如图:

参考资料:

小小石头的那些事儿  :  http://blog.csdn.net/yezhenxu1992/article/details/50820629

菜鸟教程               :  http://www.runoob.com/mongodb/mongodb-tutorial.html

node.js+mongodb 爬虫的更多相关文章

  1. 8 步搭建 Node.js + MongoDB 项目的自动化持续集成

    任何事情超过 90 秒就应该自动化,这是程序员的终极打开方式.Automating shapes smarter future. 这篇文章中,我们通过创建一个 Node.js + MongoDB 项目 ...

  2. 《Node.js+MongoDB+AngularJS Web开发》读书笔记及联想

    总体介绍 <Node.js+MongoDB+AngularJS Web开发>,于2015年6月出版,是一本翻译过来的书,原书名为<Node.js,MongoDB and Angula ...

  3. Node.JS + MongoDB技术浅谈

    看到一个Node.JS + MongoDB的小样例,分享给大家.魔乐科技软件学院(www.mldnjava.cn)的讲座 Node.JS + MongoDB技术讲座          云计算 +大数据 ...

  4. AngularJS + Node.js + MongoDB开发

    AngularJS + Node.js + MongoDB开发的基于位置的通讯录(by vczero) 一.闲扯 有一天班长说了,同学们希望我开发一个可以共享位置的通讯录,于是自己简单设计了下功能.包 ...

  5. node.js + mongodb

    node.js + mongodb 这次内容是结合bootstrap把登陆注册做好,还有就是express的中间件等问题. 看这篇博客之前建议先看我上篇写的那篇博客http://www.cnblogs ...

  6. 用Node.JS+MongoDB搭建个人博客(页面模板)(五)(结束)

    <差不多先生> 我是差不多先生,我的差不多是天生.也代表我很天真,也代表我是个闲人.这差不多的人生,总是见缝插针. 求学的道路上总是孤独的,即使别人不理解我,认为我是奇葩!但没关系,我会坚 ...

  7. 用Node.js写爬虫,撸羞羞的图片

    说到爬虫,很多人都认为是很高大上的东西.哇塞,是不是可以爬妹纸图啊,是不是可以爬小片片啊.答案就是对的.爬虫可以完成这些东西的操作.但是,作为一个正直的程序员,我们要在法律允许范围内用爬虫来为我们服务 ...

  8. CentOS 7部署Node.js+MongoDB:在VPS上从安装到Hello world

    写好代码,花钱买了VPS,看着Charges一直上涨却无从下手?记一位新手司机从购买VPS到成功访问的过程 0.购买VPS 首先,选择VPS提供商,部署一个新的服务器(Deploy New Serve ...

  9. 基于node.js制作爬虫教程

    前言:最近想学习node.js,突然在网上看到基于node的爬虫制作教程,所以简单学习了一下,把这篇文章分享给同样初学node.js的朋友. 目标:爬取 http://tweixin.yueyishu ...

随机推荐

  1. MR-join连接1......

    MR-join连接

  2. win10下安装ubuntu18.04

    在win10下安装Ubuntu18.04,双系统共存.Ubuntu 18.04 使用的是Gnome桌面. 查看系统的启动模式: Win+R打开运行,输入msinfo32,回车查看系统信息.在BIOS模 ...

  3. laravel 定义翻译字符串

    https://learnku.com/docs/laravel/5.6/localization/1376 // 全景链接$data['share_phone'] = trans('web.host ...

  4. 题解 P2763 【试题库问题】

    这题可以用网络流,但我用的是匈牙利算法 进入正题 设第个类型需要个.将每个类型拆成个点,用一个边集数组记录它拆成的点. 第个试题有个类型,分别将与拆成的点连边,这样便构成了一个二分图. 使用匈牙利算法 ...

  5. Spring Boot 2.x 编写 RESTful API (二) 校验

    用Spring Boot编写RESTful API 学习笔记 约束规则对子类依旧有效 groups 参数 每个约束用注解都有一个 groups 参数 可接收多个 class 类型 (必须是接口) 不声 ...

  6. 1.nginx_add_after_body

    语法: add_before_body uri;默认值: —配置段: http, server, location发起一个子请求,请求给定的uri,并且将内容追加到主题响应的内容之前. 语法: add ...

  7. Gradle+IDEA使用说明

    Gradle+IDEA使用说明 导语: IDEA拥有大量的JAVA开发者拥护,相比于开源的eclipse,IDEA拥有更简洁直观的界面,拥有更强大的自动补全功能,号称能“一路敲回车完成编码”.如果把I ...

  8. Git-01-上传项目到github

    function fun1(){ Git上传项目到github Folder-->Git bash here Execute command: --git clone 仓库地址     多出一个 ...

  9. CBV源码分析

    1 在views中写一个类,继承View,里面写get方法,post方法 2 在路由中配置: url(r'^test/', views.Test.as_view()),实际上第二个参数位置,放的还是一 ...

  10. 记录一次群答问:jmeter正则提取器提取一个及多个值

    图截得比较大,浏览器放大倍数看吧^_^ 前几天,在群里被@,咨询这样一个问题:服务器返回:name="tom"  value="jerry"  要提取出name ...