上次的网页爬虫写完后,又打算做一个爬图的工具。前两天已经写好了代码。思路如下:

分析页面还是采用cheerio,对<div>中的img进行分析抽取,拿到图片的url。然后用childprocess调用系统的curl工具来下载这些远程url的图片。最后将这些写入到系统的硬盘中。

功能代码如下(只是下载图片的功能代码):

var url=require('url');
var fs=require('fs');
var cp=require('child_process'); var DOWNLOAD_DIR='./';
var file_url='http://htmljs.b0.upaiyun.com/uploads/1396874069658-nodejs_1280x1024.png'; function downloads(file_url){
var filename=url.parse(file_url).pathname.split('/').pop();
var file=fs.createWriteStream(DOWNLOAD_DIR+filename);
var curl=cp.spawn('curl',[file_url]); //use spawn
curl.stdout.on('data',function(data){
file.write(data);
});
curl.stdout.on('end',function(data){
file.end();
console.log(filename+'downloaded to'+DOWNLOAD_DIR);
}); curl.on('exit',function(code){
if(code!=0){
console.log('Failed:'+code);
}
}); }; downloads(file_url);

但是发现了一个问题。就是下载的图的数量比较少的时候,一切都还好。当循环页面下载的时候,一旦并行任务过多,立刻就不行了。因为并发量太大。

后来尝试用http的get方法来读图片,结果性能更不行,还不如系统的curl。

去cnode请教了一下,有前辈说需要限制一下并发量,用aysnc。

也是在下班后等零碎的时间,去aysnc的github(https://github.com/caolan/async)上看了一下,运行了几个实例。发现async的确不错。

先说下js异步回调的问题,按照传统的回调来,处理回调中的数据,发现只能一层套一层的。刚开始感觉这种方式不错,后来套的多了,才发现这种方式,太死了。

async是解决这个问题的。

为了解决我遇到的问题,所以着重看了一下它的控制流方面的东西。

async.series 和parallel.

这两个,一个是顺序的一个是并行的。

api里面有讲他的用法,他们都有(tasks, [callback])的参数。第一个参数是任务,第二个是得到前面任务数据的callback。

其中多个task,可以用数组,也可以用对象。本人倾向用对象。

async.series({
one: function(callback){
callback(null, 'one');
},
two: function(callback){
callback(null, 'two');
}
},
function(err, results) {
// results is now equal to: {one: 'one', two: 'two'}
});

同样,可以打印results中的某些属性,results.one什么的。

parallel和series是一样的用法。

所以,采用这种并行的方式,把之前写的工具改造一下,我们就不需要再往下套函数处理了:

var cheerio=require('cheerio');
var request=require('request');
var fs=require('fs');
var async=require('async'); var url='http://www.cnblogs.com/juepei/';
var result=new Array(); async.parallel({
one:function(cb){
request(url,function(error,res,body){
if(!error && res.statusCode==200){
var $=cheerio.load(body);
$('div').filter(function(i,ele){
if($(this).attr('class')==='postTitle'){
result.push($(this).text().trim());
}
});
//console.log(result);
cb(result);
}
});
}
},function(err,results){
if(err){
console.log(err);
}else{
console.log(results.one);
}
});

关于最后一个回调函数,必须要处理err,不然的话,会报results为undefined。这是不是async规定的,目前还不知道,如果有前辈知道为何,请赐教。

从而,再下载大量图片的时候,我们就可以采用parallelLimit(tasks, limit, [callback])这个函数,对并行任务的数量进行限制一下,就可解决问题了。晚上回去试试,看是不是已经ok了。

在此附上本人的github地址:https://github.com/ThinkCats ,大家可以相互交流,共同进步。

Nodejs异步框架——async的更多相关文章

  1. nodejs异步调用async

    犹豫nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦,async的流程控制就是为了简化这些操作var async = require('async'); 1.serie ...

  2. MVC+Spring.NET+NHibernate .NET SSH框架整合 C# 委托异步 和 async /await 两种实现的异步 如何消除点击按钮时周围出现的白线? Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法

    MVC+Spring.NET+NHibernate .NET SSH框架整合   在JAVA中,SSH框架可谓是无人不晓,就和.NET中的MVC框架一样普及.作为一个初学者,可以感受到.NET出了MV ...

  3. Nodejs异步异常处理domain

    前言 程序开发中,最麻烦的事情之一就是异常处理:对于Nodejs程序开发,最麻烦的事情莫过于异步异常处理. 以MVC的多层架构设计角度,异常总是要一层一层向上抛出,最后在客户端出打印错误.但是,Nod ...

  4. NodeJS异步I/O解析

    在现在的项目开发中,任何一个大型项目绝对不是简简单单的采用一个种语言和一种框架,因为每种语言和框架各有优势,与其死守一个,不与取各家之所长,依次得到一个高性能.搞扩展的产品. 对于一个.NET开发者, ...

  5. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  6. c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习

    c#中@标志的作用   参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...

  7. springboot:异步调用@Async

    在后端开发中经常遇到一些耗时或者第三方系统调用的情况,我们知道Java程序一般的执行流程是顺序执行(不考虑多线程并发的情况),但是顺序执行的效率肯定是无法达到我们的预期的,这时就期望可以并行执行,常规 ...

  8. 抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext

    长话短说,本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext 引言 C#异步编程语法糖async/await,使开发者很容易就能编写异步代码. ...

  9. Nodejs ORM框架Sequelize快速入门

    Nodejs ORM框架Sequelize快速入门 什么是ORM? 简单的讲就是对SQL查询语句的封装,让我们可以用OOP的方式操作数据库,优雅的生成安全.可维护的SQL代码.直观上,是一种Model ...

随机推荐

  1. Nexus 按项目类型分配不同的工厂来发布不同 项目

    但是有时候,一个公司会有很多项目[crm,oa,erp]等等的项目.如果把这些项目全部都放到releases或者snapshots中的话会有点混乱.比较好的办法是,按项目来分.每个项目一个工厂:cms ...

  2. 奇偶数判断1(if,else if语句)

    public class 奇偶数判断 { public static void main(String [] args){ float s = 9f; //取单浮点型变量s,可为任意值 float h ...

  3. 第八章 高级搜索树 (b1)B-树:动机

  4. TensorFlow—CNN—CIFAR数据集分类

  5. 神经网络出现nan原因?以及解决

    之前在TensorFlow中实现不同的神经网络,作为新手,发现经常会出现计算的loss中,出现Nan值的情况,总的来说,TensorFlow中出现Nan值的情况有两种,一种是在loss中计算后得到了N ...

  6. 对象导航查询和OID查询(补)

    ----------------siwuxie095                                 对象导航查询         以客户和联系人为例(一对多)     1.应用场景 ...

  7. 19-Javaweb项目读取本地图片通过虚拟路径

    有时会把文件存在本地如将图片等放在c.d盘等,在javaweb引用时会出现无法直接访问的问题,但是还是有办法解决的. 可以通过配置虚拟路径: 步骤一: 双击servers下面的tomcat, 在弹出的 ...

  8. ContentProvider-------------自定义的内容提供者 然后去访问

    自定义提供者 import android.content.Context; import android.database.DatabaseErrorHandler; import android. ...

  9. swiper3d横向滚动多张炫酷切换banner

    最近有了个新需求,swiper3d横向滚动多张炫酷切换banner要和elementUI里边走马灯的卡片化card 类似,但是还需要h5手机触摸滚动啊啊啊啊,昨天折腾了半个早上总算完成,今天乖乖跑来m ...

  10. SEO方式之HTTPS 访问优化详解

    SEO到底要不要做HTTPS?HTTPS对SEO的重要性 正方观点 1.HTTPS具有更好的加密性能,避免用户信息泄露: 2.HTTPS复杂的传输方式,降低网站被劫持的风险: 3.搜索引擎已经全面支持 ...