From ebe968a23ca7aa0c57a54cfffbcc2f9395d70d1b Mon Sep 17 00:00:00 2001 From: ningmengchongshui <916415899@qq.com> Date: Sat, 8 Jun 2024 21:01:41 +0800 Subject: [PATCH] feat: puppeteer --- src/core/functional.ts | 4 +- src/core/index.ts | 3 +- src/core/plugin.ts | 5 +- src/utils/config.ts | 34 +++++++++ src/utils/index.ts | 4 +- src/utils/puppeteer.ts | 157 +++++++++++++++++++++++++++++++++++++++++ src/utils/types.ts | 23 ++++++ 7 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 src/utils/config.ts create mode 100644 src/utils/puppeteer.ts create mode 100644 src/utils/types.ts diff --git a/src/core/functional.ts b/src/core/functional.ts index 0fded7d..0d48261 100644 --- a/src/core/functional.ts +++ b/src/core/functional.ts @@ -1,5 +1,5 @@ import { MessageCallBackType } from './types.js' -import plugin from '../../lib/plugins/plugin.js' +import { plugin } from './plugin.js' // 插件super默认值 export const PluginSuperDefine = { @@ -60,4 +60,4 @@ export class Events { get ok() { return this.data } -} \ No newline at end of file +} diff --git a/src/core/index.ts b/src/core/index.ts index 864e0a8..629069b 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,4 +1,3 @@ -import plugin from '../../lib/plugins/plugin.js' -export { plugin } +export * from './plugin.js' export * from './functional.js' export * from './types.js' diff --git a/src/core/plugin.ts b/src/core/plugin.ts index 518ea71..b4ff544 100644 --- a/src/core/plugin.ts +++ b/src/core/plugin.ts @@ -1,12 +1,11 @@ import { Common } from './local.js' - import { EventType } from './types.js' const stateArr = {} const SymbolTimeout = Symbol('Timeout') const SymbolResolve = Symbol('Resolve') -export default class plugin { +export class plugin { name = 'your-plugin' dsc = '无' rule: { @@ -171,7 +170,7 @@ export default class plugin { * @param type * @param isGroup */ - finish(type:string, isGroup?: boolean) { + finish(type: string, isGroup?: boolean) { const key = this.conKey(isGroup) if (stateArr[key]?.[type]) { clearTimeout(stateArr[key][type][SymbolTimeout]) diff --git a/src/utils/config.ts b/src/utils/config.ts new file mode 100644 index 0000000..68f7f40 --- /dev/null +++ b/src/utils/config.ts @@ -0,0 +1,34 @@ +/** + * + */ +export class BaseConfig { + #data: D = null + constructor(val: D) { + this.#data = val + } + /** + * 设置配置 + * @param key + * @param val + */ + set(key: T, val: D[T]) { + if (this.#data) this.#data[key] = val + return this + } + /** + * 读取配置 + * @param key + * @returns + */ + all(): D { + return this.#data + } + /** + * 读取配置 + * @param key + * @returns + */ + get(key: T): D[T] | undefined { + return this.#data[key] + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 693da49..240aa95 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1 +1,3 @@ -export {} \ No newline at end of file +export * from './config.js' +export * from './puppeteer.js' +export * from './types.js' \ No newline at end of file diff --git a/src/utils/puppeteer.ts b/src/utils/puppeteer.ts new file mode 100644 index 0000000..296cc9e --- /dev/null +++ b/src/utils/puppeteer.ts @@ -0,0 +1,157 @@ +import { type PuppeteerLaunchOptions } from 'puppeteer' +import puppeteer, { Browser } from 'puppeteer' +import { ScreenshotFileOptions } from './types.js' +import { BaseConfig } from './config.js' + +export const PuppeteerLunchConfig = new BaseConfig({ + // 禁用超时 + timeout: 0, //otocolTimeout: 0, + // 请求头 + headless: true, + // + args: [ + '--disable-gpu', + '--disable-dev-shm-usage', + '--disable-setuid-sandbox', + '--no-first-run', + '--no-sandbox', + '--no-zygote', + '--single-process' + ] + // 设置浏览器默认尺寸 + // defaultViewport: { + // width: 1280, + // height: 853, + // isMobile: true + // } +}) + +export class Puppeteer { + // 截图次数记录 + #pic = 0 + // 重启次数控制 + #restart = 200 + // 应用缓存 + #browser: Browser | null = null + // 状态 + #isBrowser = false + // 配置 + #launch: PuppeteerLaunchOptions = PuppeteerLunchConfig.all() + + /** + * 设置 + * @param val + */ + setLaunch(val: PuppeteerLaunchOptions) { + this.#launch = val + return this + } + + /** + * 获取 + * @returns + */ + getLaunch(): PuppeteerLaunchOptions { + return this.#launch + } + + /** + * 启动pup + * @returns + */ + async start() { + try { + this.#browser = await puppeteer.launch(this.#launch) + this.#isBrowser = true + console.info('[puppeteer] open success') + return true + } catch (err) { + this.#isBrowser = false + console.error('[puppeteer] err', err) + return false + } + } + + /** + * 启动pup检查 + * @returns 是否启动成功 + */ + async isStart() { + /** + * 检测是否开启 + */ + if (!this.#isBrowser) { + const T = await this.start() + if (!T) return false + } + if (this.#pic <= this.#restart) { + /** + * 记录次数 + */ + this.#pic++ + } else { + /** + * 重置次数 + */ + this.#pic = 0 + console.info('[puppeteer] close') + this.#isBrowser = false + this.#browser?.close().catch(err => { + console.error('[puppeteer] close', err) + }) + console.info('[puppeteer] reopen') + if (!(await this.start())) return false + this.#pic++ + } + return true + } + + /** + * 截图并返回buffer + * @param htmlPath 绝对路径 + * @param tab 截图元素位 + * @param type 图片类型 + * @param quality 清晰度 + * @param timeout 响应检查 + * @returns buffer + */ + async render( + htmlPath: string | Buffer | URL, + Options?: ScreenshotFileOptions + ) { + if (!(await this.isStart())) return false + try { + const page = await this.#browser?.newPage().catch(err => { + console.error(err) + }) + if (!page) return false + await page.goto(`file://${htmlPath}`, { + timeout: Options?.timeout ?? 120000 + }) + const body = await page.$(Options?.tab ?? 'body') + if (!body) return false + console.info('[puppeteer] success') + const buff: string | false | Buffer = await body + .screenshot( + Options?.SOptions ?? { + type: 'png' + } + ) + .catch(err => { + console.error('[puppeteer]', 'screenshot', err) + return false + }) + await page.close().catch(err => { + console.error('[puppeteer]', 'page close', err) + }) + if (!buff) { + console.error('[puppeteer]', htmlPath) + return false + } + return buff + } catch (err) { + console.error('[puppeteer] newPage', err) + return false + } + } +} \ No newline at end of file diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..8838935 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,23 @@ +import { type ScreenshotOptions, type PuppeteerLifeCycleEvent } from 'puppeteer' + +import queryString from 'querystring' + +export interface ScreenshotFileOptions { + SOptions?: { + type: 'jpeg' | 'png' | 'webp' + quality: number + } + tab?: string + timeout?: number +} + +export interface ScreenshotUrlOptions { + url: string + time?: number + rand?: ScreenshotOptions + params?: queryString.ParsedUrlQueryInput + tab?: string + timeout?: number + cache?: boolean + waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[] +}