组合设计模式
html
以及写入文件的操作单独抽离出来复用 (crowller.ts
)analyze.ts
)crowller.ts
中调用不同的分析器analyze.ts
,实现逻辑的组合设计单例模式
analyze.ts
只需要一次初始化即可,采用单例模式来实现。/* * crowller.ts:爬虫器 */ // 抓取html import superagent from 'superagent'; import fs from 'fs'; import path from 'path'; import SelfAnalyzer from './analyzer'; export interface Analyzer { analyze: (html: string, filePath: string) => string; } class Crowller { private filePath = path.resolve(__dirname, '../dist/data.json'); constructor(private url: string, private analyzer: Analyzer) { this.init(); } private async getHtml() { const res = await superagent.get(url); return res.text; } private writeFile(fileContent: string) { fs.writeFileSync(this.filePath, fileContent); } private async init() { const html = await this.getHtml(); const fileContent = this.analyzer.analyze(html, this.filePath); this.writeFile(fileContent); } } const secret = 'x3b174jsx'; const url = `http://www.dell-lee.com/typescript/demo.html?secret=${secret}`; const analyzer = SelfAnalyzer.getInstance(); new Crowller(url, analyzer);
/* * anylyze.ts: 分析器 */ // 获取节点元素 import * as cheerio from 'cheerio'; import fs from 'fs'; import { Analyzer } from './crowller'; interface Course { title: string; count: number; } interface CourseInfo { time: number; data: Course[]; } interface FileContent { [prop: number]: Course[]; } export default class SelfAnalyzer implements Analyzer { private static instance: SelfAnalyzer; private constructor() {} static getInstance() { if (!SelfAnalyzer.instance) { SelfAnalyzer.instance = new SelfAnalyzer(); } return SelfAnalyzer.instance; } private getCourseInfo(html: string) { const $ = cheerio.load(html); const $courseItems = $('.course-item'); const courseInfos: Course[] = []; $courseItems.map((index, ele) => { const descs = $(ele).find('.course-desc'); const title = descs.eq(0).text(); const count = parseInt(descs.eq(1).text().split(':')[1]); courseInfos.push({ title, count }); }); return { time: new Date().getTime(), data: courseInfos, }; } private genJSON(courseInfo: CourseInfo, filePath: string) { let fileContent: FileContent = {}; if (fs.existsSync(filePath)) { try { fileContent = JSON.parse(fs.readFileSync(filePath, 'utf-8')); } catch (e) { console.log('无法解析'); } } fileContent[courseInfo.time] = courseInfo.data; return fileContent; } analyze(html: string, filePath: string) { const courseInfo = this.getCourseInfo(html); const fileContent = this.genJSON(courseInfo, filePath); return JSON.stringify(fileContent); } }