關於Puppeteer的那些事兒

最近開始上手一個自動化測試工具Puppeteer,來談一談關於它的一些事兒。html

Puppeteer中文文檔:https://zhaoqize.github.io/puppeteer-api-zh_CN/#?product=Puppeteer&version=v1.20.0&show=api-class-puppeteer(推薦看完預熱視頻後再讀API)git

Puppeteer官方文檔:https://github.com/GoogleChrome/puppeteergithub

預熱視頻:https://www.youtube.com/watch?v=IvaJ5n5xFqU    以及     https://www.youtube.com/watch?v=ARt3zDHSsd4typescript

在線編寫測試網站:https://try-puppeteer.appspot.com/npm

puppeteer社區:https://slack.com/api

√安裝

安裝puppeteer瀏覽器

cnpm i puppeteer

安裝puppeteer-coreapp

cnpm i puppeteer-core

√經常使用方法或屬性:

1. puppeteer.launch([options])框架

//Puppeteer 模塊提供了一種啓動 Chromium 實例的方法。 下面就是使用 Puppeteer 進行自動化的一個典型示例:
const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { const page = await browser.newPage(); await page.goto('https://www.google.com'); // 其餘操做...
 await browser.close(); });

2.Browser less

當 Puppeteer 鏈接到一個 Chromium 實例的時候會經過 puppeteer.launch 或 puppeteer.connect 建立一個 Browser 對象。

//下面是使用 Browser 建立 Page 的例子
const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { // 存儲節點以便能從新鏈接到 Chromium
  const browserWSEndpoint = browser.wsEndpoint(); // 從 Chromium 斷開和 puppeteer 的鏈接
 browser.disconnect(); // 使用節點來從新創建鏈接
  const browser2 = await puppeteer.connect({browserWSEndpoint}); // 關閉 Chromium
 await browser2.close(); });
//一個斷開鏈接和重連到 Browser 的例子:
const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { // 存儲節點以便能從新鏈接到 Chromium
  const browserWSEndpoint = browser.wsEndpoint(); // 從 Chromium 斷開和 puppeteer 的鏈接
 browser.disconnect(); // 使用節點來從新創建鏈接
  const browser2 = await puppeteer.connect({browserWSEndpoint}); // 關閉 Chromium
 await browser2.close(); });

 3.Page

Page 提供操做一個 tab 頁或者 extension background page 的方法。一個 Browser 實例能夠有多個 Page 實例。

下面的例子建立一個 Page 實例,導航到一個 url ,而後保存截圖:

const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { const page = await browser.newPage(); await page.goto('https://example.com'); await page.screenshot({path: 'screenshot.png'}); await browser.close(); });

4.Keyboard 

Keyboard 提供一個接口來管理虛擬鍵盤. 高級接口爲 keyboard.type, 其接收原始字符, 而後在你的頁面上生成對應的 keydown, keypress/input, 和  keyup 事件.

爲了更精細的控制(虛擬鍵盤), 你可使用 keyboard.down, keyboard.up 和 keyboard.sendCharacter 來手動觸發事件, 就好像這些事件是由真實的鍵盤生成的.

//持續按下 Shift 來選擇一些字符串而且刪除的例子:

await page.keyboard.type('Hello World!'); await page.keyboard.press('ArrowLeft'); await page.keyboard.down('Shift'); for (let i = 0; i < ' World'.length; i++) await page.keyboard.press('ArrowLeft'); await page.keyboard.up('Shift'); await page.keyboard.press('Backspace'); // 結果字符串最終爲 'Hello!'
//按下A的例子
await page.keyboard.down('Shift'); await page.keyboard.press('KeyA'); await page.keyboard.up('Shift');

 5. Mouse 

Mouse 類在相對於視口左上角的主框架 CSS 像素中運行。

每一個 page 對象都有它本身的 Mouse 對象,使用見 page.mouse。

// 使用 ‘page.mouse’ 追蹤 100x100 的矩形。
await page.mouse.move(0, 0); await page.mouse.down(); await page.mouse.move(0, 100); await page.mouse.move(100, 100); await page.mouse.move(100, 0); await page.mouse.move(0, 0); await page.mouse.up();

 更多方法和屬性請閱讀官網

 

√實戰01:跳轉指定頁面

源碼:跳轉到百度首頁

const puppeteer=require('puppeteer'); (async ()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page= await browser.newPage(); await page.goto("https://www.baidu.com"); })();

效果:

 

√實戰02:輸入文本與元素點擊

代碼:在百度中搜索

const puppeteer=require('puppeteer'); (async ()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page= await browser.newPage(); await page.goto("https://www.baidu.com");  //跳轉頁面
    const input_text= await page.$("#kw");     //獲取百度首頁的搜索框。page.$()用來查找元素
    await input_text.type("Hello Word!");      //type()輸入內容
    const btn_click=await page.$("#su");       //獲取百度首頁的搜索按鈕。
    await btn_click.click();                   //點擊搜索按鈕。
 })();

效果:

√實戰03:獲取文本元素值

源碼:獲取百度詞條的值

const puppeteer=require('puppeteer'); (async ()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page= await browser.newPage(); await page.goto("https://www.baidu.com");  //跳轉頁面
    const input_text= await page.$("#kw");     //獲取百度首頁的搜索框。page.$()用來查找元素
    await input_text.type("Hello Word!");      //type()輸入內容
    const btn_click=await page.$("#su");       //獲取百度首頁的搜索按鈕。
    await btn_click.click();                  //點擊搜索按鈕。
 await page.waitFor('div#content_left > .result-op.c-container.xpath-log',{visible:true});//因爲獲取元素是異步操做,須要等待該元素加載出來
 let resultText= await page.$eval('div#content_left > .result-op.c-container.xpath-log',ele=>{return ele.innerHTML})//獲取元素並返回元素下的innerHTML。 .$eval表示獲取單個元素
    console.log("result is ",resultText);//在控制檯打印出值。
 })();

演示:

√實戰04:puppeteer文件上傳操做

代碼:在百度首頁上傳圖片

const puppeteer=require('puppeteer'); (async ()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page = await browser.newPage(); await page.goto('https://www.baidu.com'); await page.waitForSelector('span.soutu-btn');  //等待選擇元素出現
    const soutuBtn=await page.$('span.soutu-btn'); //獲取圖片按鈕
    await soutuBtn.click();                        //點擊展開圖片按鈕
 await page.waitForSelector('input.upload-pic');   //等待上傳按鈕出現
    const uploadPic=await page.$('input.upload-pic'); //獲取上傳按鈕
    await uploadPic.uploadFile('C:\\Capture.PNG');    //上傳圖片。注意:路徑要用雙斜槓。
})();

演示:

√實戰05:puppeteer處理多個元素

代碼:打印京東上的手機信息

const puppeteer = require('puppeteer'); (async()=>{ const browser=await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page =await browser.newPage(); await page.goto('https://www.jd.com'); await page.waitFor("#key"); const inputText=await page.$("#key"); await inputText.type("手機"); await page.keyboard.press('Enter'); await page.waitForSelector("ul.gl-warp > li"); const items=await page.$$eval("ul.gl-warp > li",eles=>eles.map(ele=>ele.innerText)); console.log("手機列表=",items); })();

演示:

 

√實戰06:puppeteer切換iframe進行操做

 iframe跟page的用法相似。使用前須要切換到iframe裏面並用src定位要操做的iframe。操做可參考:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-frame

代碼:自動在阿里雲的註冊iframe裏面填寫註冊信息

const puppeteer = require('puppeteer'); (async()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800}}); const page = await browser.newPage(); await page.goto("https://account.aliyun.com/register/register.html"); //切換iframe
    const frame= await page.frames().find(frame=>frame.url().includes("https://passport.aliyun.com"));//切換iframe,並找到對應src的iframe
    await frame.waitFor("input#nick"); //等待輸入框加載完成
    const nick =await frame.$("input#nick");//獲取輸入框
    await nick.type("測試用戶");//輸入數據
 })();

演示:

√實戰07:puppeteer拖拽操做阿里雲驗證碼

代碼:自動操做阿里雲驗證滑動模塊

const puppeteer = require('puppeteer'); (async()=>{ const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1000,height:800},ignoreDefaultArgs:["--enable-automation"]});//在有些頁面可能須要將automation提示去掉。使用ignoreDefaultArgs:["--enable-automation"]參數
    const page = await browser.newPage(); await page.goto("https://account.aliyun.com/register/register.html"); //切換iframe
    const frame= await page.frames().find(frame=>frame.url().includes("https://passport.aliyun.com"));//切換iframe,並找到對應src的iframe
    await frame.waitForSelector("span#nc_1_n1z");//等待滑動塊加載完成
    const span =await frame.$("span#nc_1_n1z");  //獲取滑動元素
    const spanInfo=await span.boundingBox();     //獲取滑動塊的信息,包括位置(x,y)以及寬和高
    //console.log(spanInfo);
 await frame.waitForSelector("div#nc_1_n1t"); //等待包裹滑塊的div加載完成
    const outDiv=await frame.$("div#nc_1_n1t");  //獲取包裹滑塊的div
    const outDivInfo=await outDiv.boundingBox(); //獲取包裹滑塊的div的信息,包括位置(x,y)以及寬和高
    //console.log(outDivInfo);
 await page.mouse.move(spanInfo.x,spanInfo.y);//將鼠標移動到滑塊位置
    await page.mouse.down();                     //將鼠標按下(默認是左鍵)
    for(var i=0;i<outDivInfo.width;i++){ page.mouse.move(spanInfo.x+i,spanInfo.y);//讓鼠標向左移動outDivInfo的寬度距離
 } await page.mouse.up(); //將鼠標鬆開
 })();

演示:

√實戰08:puppeteer自動抓取百度新聞上的語句並自動登陸微博帳戶發一條微博

 代碼:這個實戰彷佛翻車了,被微博檢測到自動化而被要求輸入驗證碼

const puppeteer = require('puppeteer'); const config=require('./config'); //爲了保護個人我的隱私,因此我把帳號和密碼保存在了config文件中
 (async ()=>{ // console.log(config.username);
    // console.log(config.password);
    const browser = await puppeteer.launch({ headless:false, defaultViewport:{width:1280,height:800}, ignoreDefaultArgs:["--enable-automation"],//移除自動化,防止頁面生成驗證碼
        slowMo:200,//輸入延遲時間
        args:['--window-size:1280,800'],//調整窗口大小
 }); const page= await browser.newPage(); await page.goto('https://news.baidu.com/',{waitUntil:"networkidle2"});//第一個參數是要前往的地址url,第二個參數是保證頁面所有加載
 await page.waitForSelector('#imgTitle>a>strong'); const newsText=await page.$eval("#imgTitle>a>strong",ele=>ele.innerText);//匹配第一個元素
    // console.log(newsText);
 await page.goto('https://weibo.com',{waitUntil:"networkidle2"}); await page.waitFor(5*1000);//防止被檢測
    await page.reload();//防止被檢測
 await page.waitForSelector('#loginname');                   //等待帳號輸入框加載完成
    const inputText=await page.$('#loginname');                 //獲取帳號輸入框元素
    await inputText.click();                                    //防止被檢測,具體狀況具體分析
 await inputText.type(config.username); await page.waitForSelector('input[name="password"]');       //等待密碼輸入框加載完成
    const inputPwd=await page.$('input[name="password"]');      //獲取密碼輸入框
    await inputPwd.click();//防止被檢測,具體狀況具體分析
 await inputPwd.type(config.password); await page.waitForSelector('a[action-type="btn_submit"]');  //等待確認按鈕加載
    const submit=await page.$('a[action-type="btn_submit"]');   //獲取確認按鈕
    await submit.click();                                       //點擊
 })();

演示:翻車啦!!!

√實戰09:puppeteer模擬快捷鍵

 代碼演示:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-keyboard

√實戰10:puppeteer切換瀏覽器tab頁

主要用到api:browser.target();

文檔:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-browser

√實戰11:puppeteer處理彈出的對話框

主要用到的api:Dialog處理彈出的內容

文檔:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-dialog

√實戰12:puppeteer執行JavaScript方法

主要用到的方法:page.evaluate(()=>{  在這裏面能夠寫任意JS代碼  })

文檔:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-page

√實戰13:配置typescript環境,並在其中使用puppeteer

 待完善 

√實戰14:獲取全屏截圖

源碼:

const puppeteer =require('puppeteer');//引入puppeteer
(async()=>{//使用自執行函數
    const browser = await puppeteer.launch();//生成browser實例
 const page = await browser.newPage();//生成一個頁面
    await page.goto('https://cn.aliyun.com/');//前往頁面
 console.log(await page.content());//打印頁面信息(源碼)
    await page.screenshot({//截圖
    path: 'ali.png', fullPage: true }); await browser.close();//關閉browser實例
})();

效果圖:

代碼執行結果

相關文章
相關標籤/搜索