Commit 4c3087d4 authored by 陈豪's avatar 陈豪

init

parents
WXT_ORIGIN = 'https://www.weixiaotong.com.cn/'
DOCUMENT_WIDTH = 1500
DOCUMENT_HEIGHT = 2668
module.exports = {
"env": {
"commonjs": true,
"es2021": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12
},
"rules": {
}
};
/node_modules
/dist
\ No newline at end of file
module.exports = {
// 箭头函数只有一个参数的时候可以忽略括号
arrowParens: 'avoid',
// 括号内部不要出现空格
bracketSpacing: false,
// 行结束符使用 Unix 格式
endOfLine: 'lf',
// true: Put > on the last line instead of at a new line
jsxBracketSameLine: false,
// jsx 属性使用双引号
jsxSingleQuote: false,
// 行宽
printWidth: 80,
// 换行方式
proseWrap: 'preserve',
// 分号
semi: false,
// 使用单引号
singleQuote: true,
// 缩进
// tabWidth: 4,
// 使用空格缩进
useTabs: false,
// 后置逗号,多行对象、数组在最后一行增加逗号
trailingComma: 'none'
// parser: 'babylon',
}
{
"name": "weixt_growth_generate",
"version": "1.0.0",
"description": "",
"main": ".eslintrc.js",
"scripts": {
"test": "node ./src/server/scripts/generateImage"
},
"author": "",
"license": "ISC",
"dependencies": {
"archiver": "^5.2.0",
"chalk": "^4.1.0",
"dotenv": "^8.2.0",
"puppeteer": "2.1.1"
}
}
resources
\ No newline at end of file
const fs = require('fs')
const path = require('path')
const archiver = require('archiver')
// const {objectUtils} = require('wxt-utils')
const pathResources = path.resolve(__dirname, '../resources')
const resolve = p => path.resolve(pathResources, p)
module.exports = class Archiver {
constructor(conf) {
// create a file to stream archive data to.
let {fileName, archiverType} = this.formaterConf(conf)
// fileName : 年月日-type-campusName-className-stuName-stuId-random
let resourcesPath = resolve(fileName)
this.output = fs.createWriteStream(resourcesPath)
this.archive = archiver(archiverType, {
zlib: {level: 1} // Sets the compression level.
})
// listen for all archive data to be written
// 'close' event is fired only when a file descriptor is involved
this.output.on('close', () => {
console.log(this.archive.pointer() + ' total bytes')
console.log(
'archiver has been finalized and the output file descriptor has closed.'
)
})
// This event is fired when the data source is drained no matter what was the data source.
// It is not part of this library but rather from the NodeJS Stream API.
// @see: https://nodejs.org/api/stream.html#stream_event_end
this.output.on('end', () => {
console.log('Data has been drained')
})
// good practice to catch warnings (ie stat failures and other non-blocking errors)
this.archive.on('warning', err => {
if (err.code === 'ENOENT') {
// log warning
} else {
// throw error
throw err
}
})
// good practice to catch this error explicitly
this.archive.on('error', function (err) {
throw err
})
// pipe archive data to the file
this.archive.pipe(this.output)
}
archiveAppend(buffer, name) {
this.archive.append(buffer, {name})
}
archiveFinalize() {
this.archive.finalize()
}
formaterConf(conf = {}) {
// conf 格式整理-校验
const time = new Date().toLocaleDateString()
const random = (+new Date()).toString(16)
let {
growthType = 'default',
campusName = '学校',
className = '班级',
stuName = '张三',
stuId = '001',
archiverType = 'zip'
} = conf
// = objectUtils.safeObject(conf)
// generate fileName
let zipFileName = `${time}-${growthType}-${campusName}-${className}-${stuName}-${stuId}-${random}.${archiverType}`
return Object.assign(
{
fileName: this.replaceOSSInvaildSymbol(zipFileName),
archiverType
},
conf
)
}
replaceOSSInvaildSymbol(path) {
if (typeof path === 'string') {
// 当文件中包含如下字符时会上传错误,要进行替换。
;['s', '+', '(', ')', '(', ')'].forEach(item => {
path = path.replace(new RegExp(`\\${item}`, 'g'), '')
})
return path
}
return
}
}
const path = require('path')
const pathResources = path.resolve(__dirname, '../resources')
const resolve = p => path.resolve(pathResources, p)
// conf
const documentWidth = process.env.DOCUMENT_WIDTH - 0
const documentHeight = process.env.DOCUMENT_HEIGHT - 0
module.exports = async function generation(page, url, pageIndex) {
/**
脚步方式打开目标界面
*/
await page.setViewport({width: documentWidth, height: documentHeight})
await page.goto(url, {
timeout: 120000 // 请求超时时间
// waitUntil: []
})
/**
可以在页面中定义自己认为加载完的事件,在合适的时间点我们将该事件设置为 true
以下是在触发截图时的判断逻辑。
如果 renderdone 出现且为 true 那么就截图。
如果是 Object(null),说明页面加载出错了,我们可以捕获该异常进行提示
*/
// let renderdoneHandle = await page.waitForFunction('window.renderdone', {
// polling: '120' // 轮询时间间隔。 raf/mutation
// })
// const renderdone = await renderdoneHandle.jsonValue()
// if (renderdone === null) {
// throw new Error(
// `加载页面失败:报表${renderdone.componentId}出错 -- ${renderdone.message}`
// )
// } else {
// console.log('页面加载成功')
// }
/**
截图
文档:https://github.com/puppeteer/puppeteer/blob/v7.1.0/docs/api.md#pagescreenshotoptions
*/
return page.screenshot({
type: 'jpeg',
quality: 100,
fullPage: true
})
}
require('dotenv').config()
const puppeteer = require('puppeteer')
const {infoLog, warnningLog, successLog, log} = require('../../utils/console')
const generation = require('../generation/image')
const {urls} = require('../../test.response')
const Archiver = require('../compression/archiver')
;(async function () {
let generatesTime = +new Date()
// ready puppeteer (browser / page)
// https://zhaoqize.github.io/puppeteer-api-zh_CN/#?product=Puppeteer&version=v2.1.1&show=api-puppeteerlaunchoptions
const browser = await puppeteer.launch({
headless: true, // false将有浏览器界面启动
// slowMo: 100, // 放慢浏览器执行速度,方便测试观察
args: [
// 启动 Chrome 的参数,
// https://peter.sh/experiments/chromium-command-line-switches/
'--no-sandbox',
'--disable-setuid-sandbox' // 关闭沙箱
],
// 是否将浏览器进程标准输出和标准错误输入到 process.stdout 和 process.stderr 中
dumpio: false
})
const browserPage = await browser.newPage()
const compression = new Archiver({})
// generate
for (let i = 0, length = urls.length; i < length; i++) {
let targetUrl = urls[i]
try {
// 浏览目标地址并生成图片
const generationTime = +new Date()
warnningLog(`generate url:${targetUrl}`)
let imageBuf = await generation(browserPage, targetUrl)
// zip
compression.archiveAppend(imageBuf, `${i + i}.jpeg`)
infoLog(
`[time consuming - generation] :${+new Date() - generationTime} ms \n`
)
} catch (e) {
console.log(`Destination address (${targetUrl}) failed to generate image`)
}
}
// close
compression.archiveFinalize()
await browserPage.close()
await browser.close()
successLog(`[Total time]: ${+new Date() - generatesTime} \n`)
})()
// module.exports = generates
module.exports = {
urls: [
'https://www.weixiaotong.com.cn/weixt/mportal/microportal/newsdetail/1017975/0',
'https://www.weixiaotong.com.cn/weixt/mportal/microportal/newsdetail/1028700/%E8%82%B2%E5%84%BF%E7%9F%A5%E8%AF%86'
]
}
const chalk = require('chalk')
let log = console.log
let warnningLog = val => log(chalk.yellow(val))
let successLog = val => log(chalk.green(val))
let errorLog = val => log(chalk.red(val))
let infoLog = val => log(chalk.blue(val))
module.exports = {
log,
warnningLog,
infoLog,
successLog,
errorLog
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment