node 爬虫

Posted by czr on October 26, 2016

准备文件

准备文件spider,文件目录如下 目录 npm init 初始化package.json;

需要的模块

  1. http模块、fs模块都是内置的包
  2. 安装cheerio包,和request包(直接那么npm install)

开始编写脚本

在根目录下新建spider.js,加载包依赖

 	var http = require('http');
	var fs = require('fs');
	var cheerio = require('cheerio');
	var request= require('request');
	var i=0;
	var url="http://gz.lianjia.com/zufang/";
	//初始化url
	function fetchPage(x){//封装了一层函数
    console.log('start');
    startRequest(x);
	}
下面利用cheerio来解析html文档,筛选出需要的数据,这里cheerio的用法和jq好像基本上一样(挺简单的);把文字内容格式为类似json的key:val;用i来控制爬取内容的数量
	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 pic_panel=$('.pic-panel a').eq(i).find('img');
            var news_item = {
                //获取租房的标题
                title: $('.info-panel h2 a').eq(i).text().trim(),
                //获取租房发布的时间
                Time: $('.info-panel .price-pre').eq(i).text().trim(),
                //获取租房的url
                link:  $(".info-panel h2 a").eq(i).attr('href'),
                //获取租房价格
                price: $('.info-panel .price span').eq(i).text().trim(),
                //获取详细信息
                msg: $('.where .region').eq(i).text().trim()+$('.where .zone span').eq(i).text().trim()+$('.where .meters').eq(i).text().trim(),
                //i是用来判断获取了多少篇文章
                i: i = i + 1,

            };
            console.log(news_item);
            savedContent($,news_item);//存储内容
            savedImg($,pic_panel);//存储图片
            if (i <=20) {
                fetchPage(url);
            }
        });
    }).on('error', function (err) {
        console.log(err);
    });
	}
下面连个函数是用来把数据保存到本地的,这里有个坑,一般图片是有防爬取链接的,比如这里我选择的事img的data-img而不是src,看一下链家的接口是把图片的src在页面load的时候再切换的
	//该函数的作用:在本地存储所爬取的新闻内容资源
	function savedContent($, news_title) {
	        var x = JSON.stringify(news_title);
	//将新闻文本内容一段一段添加到/data文件夹下,并用新闻的标题来命名文件
	            fs.appendFile('./data/' + news_title.title + '.txt', x, 'utf-8', function (err) {
	                if (err) {
	                    console.log(err);
	                }
	            });
	}
	    //该函数的作用:在本地存储所爬取到的图片资源
	    function savedImg($,news_title) {
	            var img_title = news_title.attr('alt');  //获取图片的标题
	            if(img_title.length>35||img_title==""){
	                img_title="Null";}
	            var img_filename = img_title + '.jpg';

	            var img_src =  news_title.attr('data-img'); //获取图片的url
	            console.log(img_src)

	//采用request模块,向服务器发起一次请求,获取图片资源
	            request.head(img_src,function(err,res,body){
	                if(err){
	                    console.log(err);
	                }
	            });
	            request(img_src).pipe(fs.createWriteStream('./image/'+img_title + '---' + img_filename));     //通过流的方式,把图片写到本地/image目录下,并用新闻的标题和图片的标题作为图片的名称。
	    }

最后执行函数

	    fetchPage(url);      //主程序开始运行

这是爬取的图片 目录 这是爬取的文档 目录 这是爬取的文档内容 目录


Creative Commons License
This work is licensed under a CC A-S 4.0 International License.