小言_互联网的博客

基于NodeJs的爬虫

346人阅读  评论(0)

参考博客:手把手教你做爬虫—基于NodeJs
第一个nodejs爬虫:爬取豆瓣电影图片

引入模块

1.node 必须安装
2.http模块、fs模块都是内置的包,不需要额外添加
cheerio包,request包和async包,需要用npm或cnpm安装

cheerio包:是一个有着jQuery类似语法的文档解析模块,可以简单理解为nodejs中的jQuery。
async包:是一个异步流程控制模块用来控制并发,因为很多网站都有并发连接数量的限制,所以当请求发送太快的时候会导致返回值为空或报错。更有甚者,有些网站可能因为你发出的并发连接数量过多而当你是在恶意请求,封掉你的ip。

cnpm i cheerio -S
cnpm i request -S
cnpm i async -S

代码

创建index.js

var http = require('https'); //使用https模块(内置的包)
var fs = require('fs');//文件读写内置的包
var cheerio = require('cheerio');//jquery写法获取所得页面dom元素(须安装)
var request = require('request');//发送request请求(须安装)
var async = require('async');//控制并发(须安装)
var i = 0;
var url = "https://movie.douban.com/subject/1889243/?from=subject-page";
//判断data是否存在,创建data文件夹存储文本
fs.exists("./data", function (exists) {
    if (exists) {
        console.log("data目录存在")
    } else {
        console.log("data目录不存在")
        fs.mkdir('./data/', function (err) {
            if (err) {
                return console.error(err);
            }
            console.log("data目录创建成功。");
        });
    }
});
//判断image是否存在,不存在就创建image文件夹存储图片
fs.exists("./image", function (exists) {
    if (exists) {
        console.log("image目录存在")
    } else {
        console.log("image目录不存在")
        fs.mkdir('./image/', function (err) {
            if (err) {
                return console.error(err);
            }
            console.log("image目录创建成功。");
        });
    }
});

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

//初始url 
function fetchPage(x) { //封装一层函数,方便递归调用
    startRequest(x);
}

function startRequest(x) {
    //采用http模块向服务器发起一次get请求      
    http.get(x, function (res) { //get到x网址,成功执行回调函数
        var html = ''; //用来存储请求网页的整个html内容
        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 news_item = {
                //获取电影的标题
                title: $('.related-info h2 i').text().trim(),
                //i是用来判断获取页数
                i: i = i + 1,
            };

            console.log(news_item); //打印新闻信息
            var news_title = $('.related-info h2 i').text().trim();

            savedContent($, news_title); //存储每篇文章的内容及文章标题

            savedImg($, news_title); //存储每篇文章的图片及图片标题

            //下一篇电影的url
            nextLink = $(".recommendations-bd dl:last-child dd a").attr('href');
            if (i < 10) { //爬取10页
                fetchPage(nextLink);
            }
        });
    }).on('error', function (err) { //http模块的on data,on end ,on error事件
        console.log(err);
    });

}
//存储每篇文章的内容
function savedContent($, news_title) {
    var text = '';
    $('#link-report span').each(function (index, item) {
        text += $(this).text();
        text += '\n';
    })
    //将新闻文本内容一段一段添加到/data文件夹下,并用新闻的标题来命名文件
    fs.appendFile('./data/' + news_title + Math.random() + '.txt', text, 'utf-8', function (err) {
        if (err) {
            console.log(err);
        }
    });
}
//储所爬取到的图片资源
function savedImg($, news_title) {
    var fileName = './image/' + news_title + Math.random() + '/';
    var imgList = []; // 存储下载图片列表
    fs.mkdir(fileName, function (err) {
        if (err) {
            return console.error(err);
        }
        console.log("目录创建成功。");
    });
    $('#recommendations img').each(function (index, item) {
        var img_title = $(this).text().trim(); //获取图片的标题
        if (img_title.length > 35 || img_title == "") { //图片标题太长
            img_title = "图片";
        }
        var img_filename = img_title + Math.random() + '.jpg';
        var img_src = $(this).attr('src'); //获取图片的url
        imgList.push({
            img_title: img_title,
            img_filename: img_filename,
            img_src: img_src
        });
    });
    //并发请求一次发送五个
    async.mapLimit(imgList, 5, function (obj, callback) {
        //采用request模块,向服务器发起一次请求,获取图片资源
        request.head(obj.img_src, function (err, res, body) {
            if (err) {
                console.log(err);
            }
            request(obj.img_src).pipe(fs.createWriteStream(fileName + obj.news_title + '---' + obj.img_filename));
            //通过流的方式,把图片写到本地/image目录下,并用标题和图片的标题作为图片的名称。
            callback(null);
        });
    }, function (err, result) {
        if (err) {
            console.log(err);
        } else {
            // console.log(result);<=会输出一个有2万多个“successful”字符串的数组
            console.log("全部已下载完毕!");
        }
    });
}

运行

node index.js

结果


福利(获取妹子图片)

var http = require('https'); //使用https模块
var fs = require('fs');//文件读写
var cheerio = require('cheerio');//jquery写法获取所得页面dom元素
var request = require('request');//发送request请求
var url = "https://www.nanrentu.cc/mntp/swmn.html";
//判断image是否存在,不存在就创建image文件夹存储图片
fs.exists("./image", function (exists) {
    if (exists) {
        console.log("image目录存在")
    } else {
        console.log("image目录不存在")
        fs.mkdir('./image/', function (err) {
            if (err) {
                return console.error(err);
            }
            console.log("image目录创建成功。");
        });
    }
});

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

function startRequest(x) {
    //采用http模块向服务器发起一次get请求      
    http.get(x, function (res) { //get到x网址,成功执行回调函数
        var html = ''; //用来存储请求网页的整个html内容
        res.setEncoding('utf-8'); //防止中文乱码
        //监听data事件,每次取一块数据
        res.on('data', function (chunk) {
            html += chunk;
        });
        //监听end事件,如果整个网页内容的html都获取完毕,就执行回调函数
        res.on('end', function () {
            var $ = cheerio.load(html); //采用cheerio模块解析html
            //把跳转页面的图片的跳转地址取出来,传到详情页面
            $('.h-piclist li').each(function (index, item) {
                if (index < 10) {
                    var url = $(this).find('a').attr('href');
                    var text = $(this).find('p').text();
                    console.log(text);
                    var path = './image/' + text + Math.random() + '/';
                    fs.mkdir(path, function (err) {
                        if (err) {
                            return console.error(err);
                        }
                    });
                    enterPage(url, path);
                }
            });
        });

    }).on('error', function (err) { //http模块的on data,on end ,on error事件
        console.log(err);
    });
}
//进入详情页
function enterPage(x, path) {
    //采用http模块向服务器发起一次get请求     
    http.get(x, function (res) { //get到x网址,成功执行回调函数
        var html = ''; //用来存储请求网页的整个html内容
        res.setEncoding('utf-8'); //防止中文乱码
        //监听data事件,每次取一块数据
        res.on('data', function (chunk) {
            html += chunk;
        });
        //监听end事件,如果整个网页内容的html都获取完毕,就执行回调函数
        res.on('end', function () {
            var $ = cheerio.load(html); //采用cheerio模块解析html
            savedImg($, path); //存储每篇文章的图片及图片标题
            var flag = false;
            //获取下一页的地址,然后递归跳转
            $('.page li').each(function (index, item) {
                if ($(this).find('a').text() === '下一页') {
                    flag = true;
                    url = $(this).find('a').attr('href');
                }
            });
            if (flag) {
                enterPage('https://www.nanrentu.cc' + url, path);
            }
        });

    }).on('error', function (err) { //http模块的on data,on end ,on error事件
        console.log(err);
    });
}
//存储所爬取到的图片资源
function savedImg($, path) {
    $('.info-pic-list img').each(function (index, item) {
        var img_title = $(this).attr('alt'); //获取图片的标题
        var img_filename = img_title + Math.random() + '.jpg';
        var img_src = $(this).attr('src'); //获取图片的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(path + img_filename));
        //通过流的方式,把图片写到本地/image目录下,并用标题和图片的标题作为图片的名称。
    })
}

转载:https://blog.csdn.net/document_dom/article/details/101768298
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场