关于前端:Node-系列-006-Puppeteer

41次阅读

共计 5532 个字符,预计需要花费 14 分钟才能阅读完成。

在后面的 5 篇文章打底下,咱们应该接入点接地气的业务了。

本篇开始将接触前端多语言性能。

不晓得小伙伴们有没有接触过,这一次 jsliang 将把实在的我的项目中对于多语言的解决(对,仅是解决而不是解说多语言怎么配置)脱敏后拿进去分享下。

该分享所用的数据仅为参考实在我的项目而虚构,毕竟这只是【工具库】而不是要打造反对多语言的我的项目,然而这套工具批改下还是能用到其余中央的,具备参考价值

本篇文章咱们将解说如何应用 Puppeteer 管制 Chrome/Chromium,从而达到下载文件的目标。

一 前言

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协定管制 Chromium 或 Chrome。

就跟它在 GitHub 简介中介绍的一样:你在浏览器中手动执行的绝大多数操作都能够应用 Puppeteer 来实现!

  • 抓取页面快照
  • 生成页面 PDF
  • 主动操作页面 DOM
  • ……

具体例子小伙伴能够翻看本文下方参考文献的 GitHub 或者中文文档,这里不一一举例(省得被吐槽复制 README.md)

二 Puppeteer

  • 装置:npm i puppeteer

jsliang 装置的时候报错:

  • (node:7584) ExperimentalWarning: The fs.promises API is experimental

我的 Node.js 版本是 node@10.16.0,所以须要降级 Node.js。

查了下材料有 2 种办法降级,一种是下载最新版笼罩装置,另一种是通过 nvm/nvmw 形式去治理。

jsliang 网络还不错,间接下载个最新文档版吧:Node 官网

装置结束后查看下最新版本:

  • node -vv14.17.1

这时候再装置 Puppeteer,显示装置胜利,package.json 显示:"puppeteer": "^10.0.0"

装置 Puppeteer 过程中可能会有各式各样的报错,考验小伙伴们网速的时候到了

装置结束,开始搞事~

2.1 抓取快照

咱们拿抓取页面快照做个简略举例:

src/index.ts

import program from 'commander';
import common from './common';
import './base/console';
import puppeteer from 'puppeteer';

program
  .version('0.0.1')
  .description('工具库')

program
  .command('jsliang')
  .description('jsliang 帮忙指令')
  .action(() => {common();
  });

program
  .command('test')
  .description('测试频道')
  .action(async () => {
    // 启动浏览器
    const browser = await puppeteer.launch({headless: false, // 关上实体浏览器});

    // 创立新标签页并关上
    const page = await browser.newPage();
    await page.goto('https://www.baidu.com/s?wd=jsliang');

    // 获取快照并存储到本地
    await page.screenshot({path: './src/baidu.png',});

    // 敞开窗口
    await browser.close();});

program.parse(process.argv);

执行完 npm run test 之后,src 文件夹外面会呈现图片文件 baidu.png,关上展现如下:

实测 迷信上网工具 或者 360 安全卫士会对这操作造成影响,为了避免你血压飙升,请确保这些软件的敞开

这样咱们就初步理解 Puppeteer 啦,当然它还能够导出 PDF 等,自行翻下文【参考文献】中的内容对 Puppeteer 进一步理解吧。

2.2 下载文件

既然咱们能够获取到截图,那么咱们能操作 DOM 也就难能可贵,咱们获取下线上的文件吧!

拿金山文档举例,咱们先创立一个 Excel 文件:

创立形式能够本人去玩玩,就不做解说了,金山文档地址:https://www.kdocs.cn/

而后,咱们下个环节就是须要将这个 Excel 下载下来(假如曾经请人做好翻译工作了),就是这样的 Excel:

该图片来源于网络,本次常识分享用以参考,侵权必删

而后咱们搞个简略的吧:

多语言咋样不重要,咱们目标是须要操作 Puppeteer 获取到这个 Excel 文件

OK,文件有了,咱们怎样才能下载下来呢?当初状况是:

  • 试想一下如果咱们通过 Puppeteer 关上,那是无头浏览器啊,跟无痕差不多了,如果失常登录的话,须要从新登录、进入链接,而后才是点击按钮,进行下载。

所以,这里用到金山文档的免登录链接:

众所众知免登录就是不必登陆,尽管这个解释很弱智,然而我感觉很有必要……

这里提供下面的 Demo 地址,小伙伴们能够拿来练习,然而不确保这个链接会不会哪天就被我删了,所以依照下面步骤自行设置一个吧!

  • 【金山文档 Excel 试用文件.xlsx】:https://www.kdocs.cn/l/sdwvJUKBzkK2

OK,罗里吧嗦讲了那么多前置条件,上面咱们进入正题 —— 如何获取到线下文件:

  1. 操作浏览器关上 https://www.kdocs.cn/l/sdwvJUKBzkK2
  2. 睡眠 6.66s(确保浏览器关上链接并加载页面)
  3. 而后触发【更多菜单】按钮的点击
  4. 睡眠 2s(确保更多菜单按钮点击到)
  5. 设置下载门路(确保下载地位,要不然弹窗就不好解决)
  6. 最初触发【下载】按钮的点击
  7. 睡眠 10s(确保资源下载到)
  8. 敞开窗口

下面惟一要关注的点是第 5 点,因为咱们 Windows 点击下载是会有弹窗的(并不是默认下载),所以须要提前设置好下载门路(代码中会体现)。

那么,上代码!

src/common/index.ts

import {inquirer} from '../base/inquirer';
import {Result} from '../base/interface';
import {sortCatalog} from './sortCatalog';
import {downLoadExcel} from './downLoadExcel';

const common = (): void => {
  // 问题路线:看 questionList.ts
  const questionList = [
    // q0
    {
      type: 'list',
      message: '请问须要什么服务?',
      choices: ['公共服务', '文件治理']
    },
    // q1
    {
      type: 'list',
      message: '以后公共服务有:',
      choices: ['文件排序']
    },
    // q2
    {
      type: 'input',
      message: '须要排序的文件夹为?(绝对路径)',
    },
    // q3
    {
      type: 'list',
      message: '请问须要什么反对?',
      choices: ['多语言', 'Markdown 转 Word'],
    },
    // q4
    {
      type: 'list',
      message: '请问须要什么反对?',
      choices: [
        '下载多语言资源',
        '导入多语言资源',
        '导出多语言资源',
      ],
    },
    // q5
    {
      type: 'input',
      message: '资源下载地址(HTTP)?',
      default: 'https://www.kdocs.cn/l/sdwvJUKBzkK2',
    }
  ];

  const answerList = [
    // q0
    async (result: Result, questions: any) => {if (result.answer === '公共服务') {questions[1]();} else if (result.answer === '文件治理') {questions[3]();}
    },
    // q1
    async (result: Result, questions: any) => {if (result.answer === '文件排序') {questions[2]();}
    },
    // q2
    async (result: Result, _questions: any, prompts: any) => {const sortResult = await sortCatalog(result.answer);
      if (sortResult) {console.log('排序胜利!');
        prompts.complete();}
    },
    // q3
    async (result: Result, questions: any) => {if (result.answer === '多语言') {questions[4]();}
    },
    // q4
    async (result: Result, questions: any) => {if (result.answer === '下载多语言资源') {questions[5]();}
    },
    // q5
    async (result: Result, _questions: any, prompts: any) => {if (result.answer) {const downloadResult = await downLoadExcel(result.answer);
        if (downloadResult) {console.log('下载胜利!');
          prompts.complete();}
      }
    },
  ];

  inquirer(questionList, answerList);
};

export default common;

看到下面的代码我悔恨了,为啥 Inquirer.ts 被我革新的那么恶心,弄得 jsliang 还须要顺便写个文件来表明问题序列而后才捋顺问题程序:

src/common/questionList.ts

// common 板块的问题征询路线
export const questionList = {
  '公共服务': { // q0
    '文件排序': { // q1
      '须要排序的文件夹': 'Work 工作', // q2
    },
  },
  '文件治理': { // q0
    '多语言': { // q3
      '下载多语言资源': { // q4
        '下载地址': 'Work 工作', // q5
      },
      '导入多语言资源': { // q4
        '导入地址': 'Work 工作',
      },
      '导出多语言资源': { // q4
        '导出全量资源': 'Work 工作',
        '导出单门资源': 'Work 工作',
      }
    },
    'Markdown 转 Word': '暂未反对', // q3
  },
};

写完后转入写性能上:

src/common/downLoadExcel.ts

import puppeteer from 'puppeteer';
import path from 'path';
import fs from 'fs';

export const downLoadExcel = async (link: string): Promise<boolean> => {
  // 启动浏览器
  const browser = await puppeteer.launch({
    headless: false, // 关上实体浏览器
    devtools: true, // 关上开发模式
  });

  // 1. 创立新标签页并关上
  const page = await browser.newPage();
  await page.goto(link);

  // 2. 睡眠 6.66s - 确保页面失常关上
  await page.waitForTimeout(6666);

  // 3. 触发【更多菜单】按钮的点击
  const moreBtn = await page.$('.header-more-btn');
  moreBtn?.click();

  // 4. 睡眠 1s - 确保按钮点击到
  await page.waitForTimeout(2000);

  // 5. 设置下载门路
  const dist = path.join(__dirname, './dist');
  if (!fs.existsSync(dist)) {fs.mkdirSync(dist);
  }
  await (page as any)._client?.send('Page.setDownloadBehavior', {
    behavior: 'allow',
    downloadPath: dist,
  });

  // 6. 触发【下载】按钮的点击
  const elements = await page.$$('.header-menu-item');
  let downloadBtn;
  if (elements.length) {downloadBtn = elements[8];
  }
  if (!downloadBtn) {console.error('没找到下载按钮');
    await browser.close();}
  await downloadBtn?.click();

  // 7. 睡眠 10s - 确保资源下载到
  await page.waitForTimeout(10000);

  // 8. 敞开窗口
  await browser.close();

  return await true;
};

这样子运行之后,如果控制台不报错,那么 VS Code 展现为:

能够看到 common 目录下确实有 dist/Excel 试用文件.xlsx 了,咱们就能够接入 node-xlsx 这个库来操作 Excel 啦~

下期见!

三 参考文献

  • Github: Puppeteer
  • Puppeteer
  • puppeteer 前端利器
  • Puppeteer 之爬虫入门

jsliang 的文档库由 梁峻荣 采纳 常识共享 署名 - 非商业性应用 - 雷同形式共享 4.0 国内 许可协定 进行许可。<br/> 基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/> 本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。

正文完
 0