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文件寫的是常用的功能函數,這個是可以通用的。之前我不是說實現不了全選的功能嗎,其實可以調用common中的setOption函數實現全選的功能

 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的輸入框中輸入val
15 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 password
14   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系統沒有任何反應,估計並不支持。補充一下,我這里說的是實現不了ctrl+A的全選功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM