javascript - 关于node抓取图片,打包,异步循环程序执行顺序的问题

查看:119
本文介绍了javascript - 关于node抓取图片,打包,异步循环程序执行顺序的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

var request = require('request')
var cheerio = require('cheerio')
var fs = require('fs');
var rand = require('./routes/randm.js')
var eventproxy = require('eventproxy')
var ep = eventproxy()
var async = require('async')
var zipper = require('zip-local')
var cont = 0
var urlarr = ['。。。']//抓的link
var datatext = [];
var j = 0;
var newfolder = rand()
cont = urlarr.length
fs.mkdirSync('./public/result/' + newfolder)
async.mapLimit(urlarr, 1, function (urls, callback) {
  startRequest(urls)

  function startRequest(urls) {
    request(urls, function (error, response, body) {
      var $ = cheerio.load(body)
      cont += $('.common-productbox-product__image img').length
      //遍历下载图片
      $('.common-productbox-product__image img').each(function () {
        j++
        var imgurl = '。。。' + $(this).attr('src').split('?')[0]
        var imgname = $(this).attr('title')
        downloadPic(imgurl, './public/result/' + newfolder + '/' + imgname + '.jpg', imgname, j)
      })
      //判断是否有下一页,有的话继续遍历下一页
      var nextUrl = $('.next a').attr('href');
      if (nextUrl == 'javascript:void(0);' || typeof (nextUrl) == "undefined") {
        ep.emit('got_success')
        callback(null)
      } else if (urls.split("?").length > 1) {
        var nextpageurl = urls.split("?")[0] + nextUrl;
        // urlarr.splice(i+1,0,nextpageurl)
        startRequest(nextpageurl)
      } else {
        var nextpageurl = urls + nextUrl;
        // urlarr.splice(i+1,0,nextpageurl)
        startRequest(nextpageurl)
      }
      console.log(j + '正在爬取' + urls)
      //接收'got_success'将图片打包
      ep.after('got_success', cont, function () {
        console.log('=============================done,countis :' + cont + '======================')
        zipper.sync.zip("./public/result/" + newfolder).compress().save("./public/result/" + newfolder + ".zip")
      })
    })
  }

})
var downloadPic = function (src, dest, name, j) {
  var writeStream = fs.createWriteStream(dest, {
    autoClose: true
  })
  request(src).pipe(writeStream).on('end', function () {
    writeStream.end()
  })
  writeStream.on('finish', function () {
    console.log(j + ':' + name)
    ep.emit('got_success')
  })
}


做网页爬虫下载图片,我的需求是爬页面的指定的图片,如果有下一页继续调用startRequest抓下一页,最后所有页面都下载完毕后,把他们都一起打包,
现在是有几个问题:
1.没下载完就就执行了ep.after,并且爬了几个页就执行几遍ep.after,我想做成就执行一遍ep.after.
2.貌似程序是先打印:
正在爬取 XX页
一些数据
.
.
.
=============================done,countis :xx======================
正在爬取 XX页
一些数据
.
.
.
=============================done,countis :xx======================
正在爬取 XX页
一些数据
.
.
.
最后导致第三次输出done之后的图片没有压缩进去。
我的程序很乱,感觉异步循环request不知道从何下手了,求高手指教~~拜谢

解决方案

是因为你执行一次startRequest就绑定一次ep.after, 所以最终触发got_success事件的时候, 就一次触发多个回调了吧.

还有, 你最后的下载每一个图片的地方, 都触发一次got_success事件, 这就不可以理解了.

一般代码都会这样写


eventproxy.on('all_done', ()=>{ /* 做最后的处理工作, 例如压缩文件 */ });

function download_page(url) {
  request(url, function(page_html) {
    /* 处理页面HTML代码, 提取所有图片URL */
    var imgs = ['image_url'];
    var waits = imgs.map(get_image);
    Promise.all(waits).then(function(){
      // 图片下载完成, 分析是否有下一页, 有的话继续调用download_page()
      if (next_page_url) {
        download_page(next_page_url);
      } else {
        eventproxy.emit('all_done');
      }
    });
  });
}

function get_image(url) {
  return new Promise(function(ok, fail){
     request(url, function(img) {
       // 写入图片内容 img 到对应的文件
       // 所有操作完成后, 触发Promise的完成状态
       ok();
     });
  });
}

download_page('page_1_url_string');

这篇关于javascript - 关于node抓取图片,打包,异步循环程序执行顺序的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆