1. 程式人生 > >async太好用了,用了兩個小時寫的程式碼

async太好用了,用了兩個小時寫的程式碼

/*
 從5442網站上把所有的熱門推薦下載下來 async+cheerio+request
 */
const util = require('util');
const request = require('request');
const http = require('http');
const fs = require('fs');
const cheerio = require('cheerio');
const async = require('async');
const mkdirp = require('mkdirp');

function Picture5442() {
    this.host = 'http://www.5442.com/meinv/';
}

Picture5442.prototype = {
    main: function () {
        var self = this;

        async.auto({
            //如果是物件,需要進行繫結,否則this沒有
            readIndex: self.readIndex.bind(self),
            downloadHot: ['readIndex', self.downloadHot.bind(self),],
        }, function (err, result) {
            if (err) {
                console.error(err);
            } else {
                //console.log(util.inspect(result, true));
                console.log('所有的任務都完成');
            }
        });
    },

    //從主頁讀取要下載的內容
    readIndex: function (callback) {
        request(this.host, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var $ = cheerio.load(body);
                var links = $('div.lists.listNum.listTime.listLine a');
                var linkArr = [];
                links.each(function (i) {
                    linkArr[i] = $(this).attr('href');
                });

                //console.log('links=', util.inspect(linkArr,true));
                linkArr.push('http://www.5442.com/meinv/20140802/11261.html');
                linkArr.push('http://www.5442.com/meinv/20140705/10361.html');
                callback(null, linkArr);
            } else {
                callback(err);
            }
        });
    },

    //下載所有熱門
    downloadHot: function (result, callback) {
        var self = this;
        var urls = result.readIndex;
        if (urls.length < 1) {
            callback('沒有有效連結,讀取失敗', null);
            return;
        }

        async.auto({
            getAllFirstImage: self.getAllFirstImage.bind(self, urls),
            downloadImages: ['getAllFirstImage', self.downloadImages.bind(self)],
        }, function (err, results) {
            console.log('所有的熱門圖片已經下載完成');
            callback();
        });
    },

    //下載一個影集
    downloadGallery: function (aurl, callback) {
        //使用while迴圈,直到下載不到正確的結果的時候就退出迴圈
        if(!aurl){
            callback();
        }

        var nexturl = aurl;
        var parentcb = callback;
        var dirname;
        var m = aurl.match(/^http:\/\/.+\/(.+\/.+\/.+)\/(\d+\.jpg)/);
        if (!m) {
            callback('無效url地址,無法解析:' + aurl, null);
        } else {
            dirname = m[1];
        }

        async.auto(
            {
                init: function (callback) {
                    //建立目錄結構
                    if (!fs.existsSync(dirname)) {
                        mkdirp(dirname, function (err) {
                            if (err) {
                                console.error(err);
                                parentcb(err, null);
                                return;
                            } else {
                                console.log('建立目錄成功:' + dirname);
                                callback();
                            }
                        });
                    } else {
                        //不需要建立目錄
                        callback();
                    }
                },

                work: ['init', function (result, callback) {
                    var flagExit = false;
                    async.during(
                        function (callback) {
                            callback(null, !flagExit);
                        },
                        function (callback) {
                            console.log('開始下載:' + nexturl);
                            //request.get(nexturl).pipe()
                            http.get(nexturl, function (res) {
                                var chunks = [];
                                if (res.statusCode !== 200) {
                                    //退出迴圈
                                    console.error('下載圖片失敗,認為已經沒有可以下載的圖片了:' + nexturl);
                                    flagExit = true;
                                    //直接呼叫回撥函式退出,避免重複回撥
                                    callback();
                                    return;
                                }

                                res.on('data', function (data) {
                                    chunks.push(data);
                                });

                                res.on('end', function () {
                                    var buf = Buffer.concat(chunks);
                                    var m = nexturl.match(/^http:\/\/.+\/(.+\/.+\/.+)\/(\d+\.jpg)/);
                                    var filename = m[1] + '/' + m[2];
                                    fs.writeFile(filename, buf, function () {
                                        console.log('儲存圖片到檔案:' + filename);
                                        var m = nexturl.match(/(\d+)\.jpg$/);
                                        var nj;
                                        if (m[1][0] === '0') {
                                            if (m[1][1] < 9) {
                                                nj = '0' + (parseInt(m[1][1]) + 1);
                                            } else {
                                                nj = 10;
                                            }

                                        } else {
                                            nj = parseInt(m[1]) + 1 + '';
                                        }
                                        nj += '.jpg'
                                        //下一張圖片的位置
                                        nexturl = nexturl.replace(/\d+\.jpg/, nj);
                                        callback();
                                    });
                                });

                            })
                        },
                        function (err) {
                            console.log('跳出迴圈:' + aurl);
                            callback();
                        }
                    );
                }],
            },
            function (err, result) {
                if (err) {
                    console.error(err);
                    parentcb(err, aurl);
                } else {
                    console.log('一個影集已經下載完成:' + aurl);
                    parentcb(null, aurl);
                }
            });

    },

    //下載所有的圖片
    downloadImages: function (results, callback) {
        if ('getAllFirstImage' in results) {
            //根據第一張圖片開始不斷的下載
            var urls = results.getAllFirstImage;
            async.mapSeries(urls, this.downloadGallery.bind(this), function (err, results) {
                if (err) {
                    callback(err, null);
                } else {
                    //返回所有成功的結果回去
                    callback(null, results);
                }
            });
        } else {
            callback('獲取不到第一張圖片的資料', null);
        }
    },

    //讀取頁面的第一張圖片,剩下的累加操作
    getFirstImage: function (aurl, callback) {
        request(aurl, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var $ = cheerio.load(body);
                var images = $('#contents img');
                var firstImg = images.first().attr('src');
                var flagIndex = firstImg.lastIndexOf('!');
                if (flagIndex != -1) {
                    firstImg = firstImg.slice(0, flagIndex);
                }
                callback(null, firstImg);
            } else {
                console.error(err);
                callback(err, null);
            }
        });
    },

    //讀取所有的第一張圖片
    getAllFirstImage: function (urls, callback) {
        async.mapLimit(urls, 4, this.getFirstImage.bind(this), function (err, results) {
            //console.log('已經獲取到所有的第一張圖片地址');
            console.log('所有的第一張圖片地址:' + util.inspect(results, true));
            callback(null, results);
        });
    }
}

var pic = new Picture5442()
pic.main();