EfonMark

一番码客 : 挖掘你关心的亮点。
http://www.efonmark.com

本文目录:

[TOC]

image-20200305232705851

函数式编程、面向对象编程

前天我们用村函数的方式实现了图片的下载,今天通过封装类、event的方式,我们可以感受下面向对象的编程思想。
只要做好了对象化,就能更好的模块封装,减少重复造轮子,提高开发效率,让开发就像搭积木一样,而不是绕线团。

流程特点

每一步执行完了之后,执行下一步。可以很好的利用event的特点,完成整个过程。

重构实现

1
'use strict'
2
// 使用events模块重构爬虫项目
3
let http = require('http');
4
let iconv = require('iconv-lite');
5
let cheerio = require("cheerio");
6
let fs = require('fs');
7
let path = require('path');
8
let EventEmitter = require('events');
9
10
class GirlSpider extends EventEmitter{
11
12
    /**
13
     * 下载html的
14
     */
15
    getHtml(){
16
        //1. 先拿到目标网址的html内容
17
        http.get("http://www.27270.com/ent/meinvtupian/", res => {
18
            let data = []; // 用来存放所有的chunk
19
            res.on('data', chunk => {
20
                data.push(chunk)
21
            });
22
            res.on('end', () => {
23
                //2. 如果网页内容有乱码,就进行乱码的处理
24
                // 对data进行解码
25
                let html = iconv.decode(Buffer.concat(data), "gbk");
26
                // console.log(html);
27
                // 解码完毕不去直接调用相关方法,而通过事件来通知
28
                this.emit("getHtmlFinish", html)
29
            });
30
        });
31
    }
32
33
    /**
34
     * 从html中提取数据
35
     * @param html
36
     */
37
    extraDataFromHtml(html) {
38
        let $ = cheerio.load(html);
39
        let arr = $('div.MeinvTuPianBox>ul>li>a>i>img').toArray();
40
        let imgData = []
41
        for (let i = 0; i < arr.length; i++) {
42
            let obj = arr[i];
43
            let src = $(obj).attr("src");
44
            let title = $(obj).attr("alt");
45
            // console.log(`src: ${src}  title: ${title}`);
46
            imgData.push({
47
                src, title
48
            })
49
        }
50
        // 使用事件通知的方式,去调用其他方法
51
        this.emit("extraDataFinish", imgData)
52
    }
53
54
    /**
55
     * 下载图片
56
     * @param imgData
57
     */
58
    downloadImage(imgData) {
59
        imgData.forEach(imgObj => {
60
            http.get(imgObj.src, res => {
61
                // res本质是一个reader
62
                let imgPath = path.join("imgs", imgObj.title + path.extname(imgObj.src))
63
                let writer = fs.createWriteStream(imgPath);
64
                res.pipe(writer);
65
            });
66
        });
67
    }
68
69
    /**
70
     * 用来初始化监听器的注册,
71
     */
72
    start(){
73
        //1. 注册监听器
74
        this.on('getHtmlFinish', (html)=>{
75
            // 调用抽取数据的函数
76
            this.extraDataFromHtml(html)
77
        });
78
        this.on('extraDataFinish', (imgData)=>{
79
            this.downloadImage(imgData)
80
        })
81
82
        //2. 启动
83
        this.getHtml()
84
    }
85
}
86
87
88
// 使用爬虫
89
let girlSpider = new GirlSpider();
90
girlSpider.start();

一番雾语:运用好面向对象的思想。


免费知识星球:一番码客-积累交流
微信公众号:一番码客
微信:Efon-fighting
网站:http://www.efonmark.com

蜀ICP备19039940号

总访问量为