157 lines
3.4 KiB
TypeScript
157 lines
3.4 KiB
TypeScript
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'
|
|
]
|
|
// BOT浏览器默认尺寸 753 X 1180
|
|
})
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export class Puppeteer {
|
|
// 截图次数记录
|
|
#pic = 0
|
|
// 重启次数控制
|
|
#restart = 200
|
|
// 状态
|
|
#isBrowser = false
|
|
// 配置
|
|
#launch: PuppeteerLaunchOptions = PuppeteerLunchConfig.all()
|
|
|
|
// 应用缓存
|
|
browser: Browser | null = null
|
|
|
|
/**
|
|
* 设置
|
|
* @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, 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
|
|
}
|
|
}
|
|
}
|