使用Node.js制作爬虫教程(续:爬图)_程序猿DD的博客-程序员宝宝_node.js爬虫


使用Node.js制作爬虫教程(续:爬图)

前几天发了《使用Node.js制作爬虫教程》之后,有朋友问如果要爬文件怎么办,正好之前也写过类似的,那就直接拿过来写个续篇吧,有需要的可以借鉴,觉得不好的可以留言交流。

案例回顾

上一篇中,主要利用nodejs发起一个getData请求来得到4星角色的id列表。通过chrome开发者工具来查看页面结构,分析得出角色详细页面的URL规则和详细页面中想要抓取内容的位置。再循环遍历4星角色id列表去发起角色详细页面的请求并解析出想要收集的内容。

具体内容可再参考原文:使用Node.js制作爬虫教程

目标分析

案例回顾中提到的角色详细页面(参考样例),有不少图片内容,本文就以抓取“主动技能”的GIF图片为例,来改造一下前文的代码以完成定向抓取图片的效果。


alt=

通过Chrome查看图片对象的URL规则为:/img/as2/角色id.gif


编码过程

构建工程和引入框架

$npm init
$npm install --save superagent
$npm install --save cheerio
$npm install --save async

上篇代码逻辑

  1. 发起getData.php请求,获得所有4星角色的ID
  2. 依次循环根据char/角色id规则访问各个角色的详细页面,并解析其中需要的数据并按我们想要的方式存储起来

本篇代码逻辑:

  1. 发起getData.php请求,获得所有4星角色的ID
  2. 依次循环根据/img/as2/角色id.gif规则下载gif文件到本地

所以,只要修改上篇代码中对每个角色对象的处理逻辑部分的内容为下载文件即可。

具体代码如下:

var superagent = require('superagent'); 
var cheerio = require('cheerio');
var async = require('async');

var fs = require('fs');
var request = require("request");

console.log('爬虫程序开始运行......');

// 第一步,发起getData请求,获取所有4星角色的列表
superagent
    .post('http://wcatproject.com/charSearch/function/getData.php')
    .send({ 
        // 请求的表单信息Form data
        info: 'isempty', 
        star : [0,0,0,1,0], 
        job : [0,0,0,0,0,0,0,0], 
        type : [0,0,0,0,0,0,0], 
        phase : [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        cate : [0,0,0,0,0,0,0,0,0,0], 
        phases : ['初代', '第一期','第二期','第三期','第四期','第五期','第六期', '第七期','第八期','第九期','第十期','第十一期','第十二期','第十三期','第十四期', '第十五期', '第十六期'],
        cates : ['活動限定','限定角色','聖誕限定','正月限定','黑貓限定','中川限定','茶熊限定','夏日限定'] })
       // Http请求的Header信息
       .set('Accept', 'application/json, text/javascript, */*; q=0.01')
       .set('Content-Type','application/x-www-form-urlencoded; charset=UTF-8')
    .end(function(err, res){  

        // 请求返回后的处理
        // 将response中返回的结果转换成JSON对象
        var heroes = JSON.parse(res.text);    
           // 并发遍历heroes对象
        async.mapLimit(heroes, 5,
            function (hero, callback) {
                // 对每个角色对象的处理逻辑
                 var heroId = hero[0];    // 获取角色数据第一位的数据,即:角色id
                fetchInfo(heroId, callback);
            }, 
            function (err, result) {
                console.log('抓取的角色数:' + heroes.length);
            }
        );

    }); 

// 获取角色信息
var concurrencyCount = 0; // 当前并发数记录
var as2Url = 'http://wcatproject.com/img/as2/';
var fetchInfo = function(heroId, callback){

    // 下载链接
    var url = as2Url + heroId + '.gif';
    // 本地保存路径
    var filepath = 'img/' + heroId + '.gif';

    // 判断文件是否存在
    fs.exists(filepath, function(exists) {
        if (exists) {
            // 文件已经存在不下载
            console.log(filepath + ' is exists');
            callback(null, 'exists');
        } else {
            // 文件不存在,开始下载文件
            concurrencyCount++;
            console.log('并发数:', concurrencyCount, ',正在抓取的是', url);

            request.head(url, function(err, res, body){
                if (err) {
                    console.log('err: '+ err);
                    callback(null, err);
                }
                request(url)
                    .pipe(fs.createWriteStream(filepath))
                    .on('close', function(){
                        console.log('Done : ', url);
                        concurrencyCount --;
                        callback(null, url);
                    });
            });
        }
    });



};

主要修改内容:

fs模块和request模块的引用,前者用来读写文件,后者用来通过http请求获取文件。

var fs = require('fs');
var request = require("request");

fetchInfo函数修改成拼接url和本地保存路径,并通过request进行下载。

由于图片下载较慢修改并发数,async.mapLimit(heroes, 5, function (hero, callback)

执行情况如下,根据配置的并发数5,可以看到如下输出

$ node index.js
爬虫程序开始运行......
并发数: 1 ,正在抓取的是 http://wcatproject.com/img/as2/SS0441.gif
并发数: 2 ,正在抓取的是 http://wcatproject.com/img/as2/NS1641.gif
并发数: 3 ,正在抓取的是 http://wcatproject.com/img/as2/SS1141.gif
并发数: 4 ,正在抓取的是 http://wcatproject.com/img/as2/SS1041.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/SS0941.gif
Done :  http://wcatproject.com/img/as2/SS1141.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/SS0841.gif
Done :  http://wcatproject.com/img/as2/SS0841.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/LS0941.gif
Done :  http://wcatproject.com/img/as2/SS1041.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/LS1441.gif
Done :  http://wcatproject.com/img/as2/NS1641.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/SS0741.gif
Done :  http://wcatproject.com/img/as2/LS0941.gif
并发数: 5 ,正在抓取的是 http://wcatproject.com/img/as2/SS0641.gif

示例到此结束,有需要的去爬爬爬,至于爬什么我就不负责啦,^_^

代码参考:http://git.oschina.net/didispace/nodejs-learning

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dyc87112/article/details/73739390

智能推荐

Cocos2d 中 fnt文件生产工具 Bitmap Font Generator_杜甲同学的博客-程序员宝宝

首先 下载安装windows下免费的位图字体制作工具Bitmap Font Generator下载地址http://www.angelcode.com/products/bmfont/install_bmfont_1.13.exe2 打开软件,选择Opotion->FontSetting,来设定需要导出的字体我这里用微软雅黑。 Size可以设定字体大小,最好需要多大就设定多大,这里是32 Heig

vue中使用webpack-bundle-analyzer分析打包大小_maxiaoxin1314的博客-程序员宝宝_vue webpack-bundle-analyzer

1,在vue-cli3中:首先先安装webpack-bundle-analyzer:npm install webpack-bundle-analyzer --save-dev在vue.config.js文件中chainWebpack: (config) => { if (process.env.use_analyzer) { config.plugin("webpack-bundle-analyzer").use(require("webpack-bundle_1671465600

老男孩脱产班Linux运维51期_weixin_46241305的博客-程序员宝宝_最好资源库 男孩脱产班linux运维51期

课程目录51三剑客串讲复习day9老男孩教育-Linux运维51期-day37-综合架构模块-综合架构开场老男孩教育-Linux运维51期-day38-综合架构模块-综合架构环境部署老男孩教育-Linux运维51期-day39-综合架构模块-Rsync备份老男孩教育-Linux运维51期-day40-综合架构模块-Rsync实战老男孩教育-Linux运维51期-day41-综合架构模块-NFS存储老男孩教育-Linux运维51期-day43-综合架构模块-阶段复习老男孩教育-Linux运维5

java将数组拼接为字符串_数组拼接成字符串_邱可爱的博客-程序员宝宝

List<String> ids = ImmutableList.of("1", "2", "3");//直接用String.joinSystem.out.println(String.join(",", ids));//使用 org.apache.commons.lang.StringUtils System.out.println(StringUtils.join(array, ",")); //使用 Google Guava 中的 com.google.common.base.

利用HSSFWorkbook进行Excle的读写_zhupengqq的博客-程序员宝宝

利用HSSFWorkbook进行Excle的读写import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.i

Java面试题--Framework_五六先生的博客-程序员宝宝_如何设计一个系统

1. springmvc整合web,整合springSpringMVC中定义了一个前端控制器DispatcherServlet,这个控制器继承实现自HttpServlet;当我们在web.xml中配置了拦截路径后,前端控制器会拦截对应的请求,并调用处理器映射器HandlerMapping来查询对应的处理器Handler;前端控制器再将查询的Handler处理器发送至处理器适配器HandlerAdapter中执行对应的处理器,最后将执行结果返回给前端控制器;前端控制器通过视图解析器ViewReso

随便推点

pyQt5 时时输出显示(PyCharm QtDesigner PyUIC开发)_IT8343的博客-程序员宝宝_qt designer 显示输出数据

用QtDesigner工具进行界面绘制,注意各种插件的命名,以免生成的代码自己都看不懂。绘制好之后,再利用PyUIC把.ui文件转为.py文件。PyCharm可以集成QtDesigner PyUIC这两种工具。func.py:# -*- coding: utf-8 -*-# Form implementation generated from reading ui file ...

Idioms about music_WongKyunban的博客-程序员宝宝

Today I want to share some idioms about music.Here we go.A group of words with a meaning that cannot be deduced(英/dɪˈdjuːst/ v. 推论) from its constituent(英/kənˈstɪtjuənt/ n.构成要素) parts.Pop music have a good rhythm, a catchy melody, and are easy to remembe

解决使用Sql/plus插入数据出现的中文乱码问题_食梦鱼儿的博客-程序员宝宝

现象:使用sqlplus执行脚本,在对中文进行数据库插入的时候,出现【??????】。原因:sqlplus乱码与操作系统用户中的NLS_LANG这个环境变量有关系,如果这个与数据库字符集不一致的话就会产生乱码。解决办法:  参考文章:           http://blog.chinaunix.net/uid-21374062-id-2983324.ht

Docker 内JAVA用SVG代码转PNG , 图片中文乱码问题_gin_91的博客-程序员宝宝

场景:使用JAVA的org.apache.batik从SVG代码生成PNG图片public static void convertToPng(String svgCode, OutputStream outputStream){ try { byte[] bytes = svgCode.getBytes("utf-8"); PNGTranscoder t = new PNGTranscoder(); Tra..

Java声明数组的三种方法_篆愁君的烦恼的博客-程序员宝宝_java声明数组

这篇主要讲java的三种数组声明方式,这里采用String类型作为典型总结后记:三种方法各有优劣,第三种的限制比较大,尽量使用前两种作为一个优秀的码农怎么能不多会几种数组声明方法~

推荐文章

热门文章

相关标签