问题描述
我用request爬取图片,为了防止ip被封,用了代理,可是用了代理后,总是报错。nodejs用到了request和async模块
function download(item,cb){ request({ url:item.img, proxy:proxys[Math.random()*proxys.length|0], method:’GET’, timeout:5000 },function(err,response,body){ if(response && response.statusCode == 200){ cb(null,item); } }).on(’error’,function(){ console.log(’下载出现异常,可能是pipe有问题,再次请求...’); download(item,cb); // cb(null,item); }).pipe(fs.createWriteStream(fileDir2+item.name+’.’+item.url_token+’.jpg’));}
download(item,cb) ,cb是async中控制流程的回调函数:
async.eachLimit(items,10,function(item,cb){ download(item,cb);},function(){...})
每次下载没几个,就报错停止运行了:
throw new assert.AssertionError({ ^AssertionError: 258 == 0at ClientRequest.onConnect (C:UsersfoxWebstormProjectsnodejs实战爬虫node_modulestunnel-agentindex.js:160:14)
如果我去掉代理的请求头,一点事都没有;如果我把上面download里面,改成 不再继续请求,直接cb(),请求失败不会报错。
.on(’error’,function(){console.log(’下载出现异常,可能是pipe有问题,再次请求...’); // download(item,cb);cb(null,item);})
请大佬看了,能不能帮我解决一下,想了很久,一直排错,不知道什么原因。
问题解答
回答1:我之前也做过几乎和你一样的功能,直接下载图片很多下载了一部分,然后报错了,最后我试着包裹一层setTimeout,类似于:
setTimeout(function(){ download(item, cb);},400);
这样居然就好了,我为此写了一篇博文的:nodejs批量下载图片,你可以参考一下
回答2:遇到这种问题,程序要有重试机制。一个好的重试机制是:在下一次尝试的时候,适当的增加sleep时间确保正确的执行。

