feat: puppeteer

This commit is contained in:
ningmengchongshui 2024-06-08 21:01:41 +08:00
parent ab46375b3d
commit ebe968a23c
7 changed files with 222 additions and 8 deletions

View File

@ -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
}
}
}

View File

@ -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'

View File

@ -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])

34
src/utils/config.ts Normal file
View File

@ -0,0 +1,34 @@
/**
*
*/
export class BaseConfig<D> {
#data: D = null
constructor(val: D) {
this.#data = val
}
/**
*
* @param key
* @param val
*/
set<T extends keyof D>(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<T extends keyof D>(key: T): D[T] | undefined {
return this.#data[key]
}
}

View File

@ -1 +1,3 @@
export {}
export * from './config.js'
export * from './puppeteer.js'
export * from './types.js'

157
src/utils/puppeteer.ts Normal file
View File

@ -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<PuppeteerLaunchOptions>({
// 禁用超时
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
}
}
}

23
src/utils/types.ts Normal file
View File

@ -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[]
}