你的位置:首页 > Java教程

[Java教程]Puppeteer——自动化脚本设计

我被分配了一个繁琐的任务,就是要给100个相同的站点做同样的配置。曾经就有做过相同的事,那时还不会写脚本,全靠手动配置。机械的配置了两天的时间,身体感觉被掏空。所以这次我决定还是写一个脚本自动的进行配置。

一、了解Puppeteer

中文版资料:https://juejin.im/entry/59ad6c4f5188250f4850dccc

官方文档(英文):https://github.com/GoogleChrome/puppeteer

Puppeteer的API(英文):https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#

 

二、环境

只安装了node环境

 

三、开发阶段

3.1 初始化项目

  引用了https://juejin.im/entry/59ad6c4f5188250f4850dccc

  项目都是以创建文件夹开始。

 $ mkdir thal $ cd thal

  初始化 NPM,填入一些必要的信息。

 $ npm init

  安装 Puppeteer。由于 Puppeteer 并不是稳定的版本而且每天都在更新,所以如果你想要最新的功能可以直接通过 GitHub 的仓库安装。

 $ npm i --save puppeteer

  Puppeteer 包含了自己的 chrome / chromium 用以确保可以无界面地工作。因此每当你安装/更新 puppeteer 的时候,他都会下载指定的 chrome 版本。

3.2 编码

3.2.1 工程的目录结构

node_modeles中的内容是从git上拉下来的,src文件夹写得是我自己的代码,我执行的是addConfig里面的文件,common中是一些基础性配置,contentHub配置内容较多,所以我另建了一个contentHub文件夹。

 

3.2.2 common.js文件写的是常用的功能函数,这个是可以通用的

 1 const config = require('./config'); 2  3 //根据选择器sel选择id为val的子项 4 async function setOption(page, sel, val) { 5 await page.evaluate((sel, val) => { 6  document.querySelector(`${sel} > option[value="${val}"]`).selected = true; 7  element = document.querySelector(sel); 8  var event = new Event('change', { bubbles: true }); 9  event.simulated = true;10  element.dispatchEvent(event);11  }, sel, val);12 }13 14 //在id为sel的输入框中输入val15 async function setTextVal(page, sel, val) {16 await page.evaluate((sel, val) => {17  document.querySelector(sel).value = val;18  element = document.querySelector(sel);19  var event = new Event('change', { bubbles: true });20  event.simulated = true;21  element.dispatchEvent(event);22  }, sel, val);23 }24 25 //判断选择器是否存在26 async function isExist(page, selector) {27 var is = await page.evaluate((sel) => {28  const element = document.querySelector(sel);29  if (!element) {30  return false;31  } else {32  return true;33  }34  }, selector);35 36 return is;37 }38 39 //导入单个配置40 async function importSingleConfiguration(page, configType, configContent) {41 const confirmBtn = 'input[value="Confirm"]';42 const configTypeSel = '#edit-config-type';43  await setOption(page, configTypeSel, configType);44 await page.click('#edit-import');45 await setTextVal(page, '#edit-import', configContent);46 await page.click('#edit-submit');47  await page.waitForNavigation();48 49 const is = await isExist(page, confirmBtn);50 if (is) {51  await page.click(confirmBtn);52  await page.waitForNavigation();53  await page.waitFor(3 * config.stepWait);54  }55 }56 57 //设置checkbox中子项的值58 async function setCheckBoxVal(page, sel, val) {59 await page.evaluate((sel, val) => {60  document.querySelector(sel).checked = val;61  element = document.querySelector(sel);62  var event = new Event('change', { bubbles: true });63  event.simulated = true;64  element.dispatchEvent(event);65  }, sel, val);66 }67 68 module.exports = {69  setOption: setOption,70  setTextVal: setTextVal,71  importSingleConfiguration: importSingleConfiguration,72  isExist: isExist,73  selectAll: selectAll,74  setCheckBoxVal: setCheckBoxVal,75 76 }
View Code

 

3.2.3 config.js文件中申明了许多基础性配置

我要跳转的网站url,登录的用户名和密码,站内页面跳转的路径等信息都配置在这个文件里面

const baseUrlArray = [  {   url: '',   langcode: '',  },];const baseUrl = baseUrlArray[0].url;const getUrl = (index) => { const baseUrl = baseUrlArray[index].url; return {  hubConnection: `${baseUrl}/example`, };}const getLangCode = (index) => { return baseUrlArray[index].langcode;}module.exports = { secondWait: 1000, stepWait: 5000, username: '', password: '', credentials: {  username: '',  password: '', }, baseUrl: baseUrl, baseUrlArray: baseUrlArray, urls: getUrl(0), getUrl: getUrl, getLangCode: getLangCode,}
View Code

 

3.2.4 login.js

 1 const config = require('./config'); 2  3 async function login(page, url = null) { 4  5 //fill authenticate user name and password 6  await page.authenticate(config.credentials); 7  8 // goto login page 9 await page.goto(url ? url : config.urls.login);10 const agreeButton = await page.$('#block-popup .btn');11  await agreeButton.click();12 13 //fill admin user name and password14 await page.focus('#edit-name');15  await page.keyboard.type(config.username);16 await page.focus('#edit-pass');17  await page.keyboard.type(config.password);18 19 const inputElement = await page.$('#edit-submit');20  await inputElement.click();21 22  await page.waitForNavigation();23 }24 25 module.exports = login;
View Code

 

3.2.5 好了,登录成功了

 

四、收获

1.需要被其它页面引用的函数,常量必须要在module.exports={}中申明

2.headles: false是设置自动化操作是可视化的

3.在输入框中输入值并覆盖原有的值:

    4.调用其他页面函数的声明:const common = require('./common');

 

五、疑惑

1.关于全选的功能,puppeteer并不支持全选,虽然官方文档上面说了linux和windows支持全选,但是我的linux系统没有任何反应,估计并不支持。