Web自動化之Headless Chrome編碼實戰
API 概覽 && 編碼Tips
文件地址
- github Chrome DevTools Protocol 協議本身的倉庫 有問題可以在這裡提issue
- 協議API文件的倉庫
- API 文件地址 API展示的地方,這個經常用
常用API
- Network 網路請求、Cookie、快取、證照等相關內容
- Page 頁面的載入、資源內容、彈層、截圖、列印等相關內容
- DOM 文件DOM的獲取、修改、刪除、查詢等相關內容
- Runtime JavaScript程式碼的執行,這裡面我們可以搞事情~~
編碼Tips
- 我們這裡不會直接呼叫Websocket相關的內容來呼叫chrome的除錯命令,而是用 這個封裝的庫來做,它是基於Promise風格的
- 每一個功能塊成為一個單獨的domain,像Network,Page,DOM等都是不同的domain
- 幾乎每一個個頭大的domain都有enable方法,需要先呼叫這個方法啟用之後再使用
- 各個domain的介面方法引數都是第一個物件或者說一個Map,不用考慮引數的位置了
- 各個domain的介面返回值也是一個物件,取對應的key就行
- 引數值和返回值經常是meta資訊,經常是各種物件的id資訊,而不是具體的物件內容(這裡可能需要切一下風格)
編碼例項
首先做一個簡單的封裝,準備API的執行環境,具體可參考前一篇關於工具庫的。
const chromeLauncher = require('chrome-launcher'); const chromeRemoteInterface = require('chrome-remote-interface'); const prepareAPI = (config = {}) => { const {host = 'localhost', port = 9222, autoSelectChrome = true, headless = true} = config; const wrapperEntry = chromeLauncher.launch({
host,
port,
autoSelectChrome,
additionalFlags: [ '--disable-gpu',
headless ? '--headless' : '' ]
}).then(chromeInstance => { const remoteInterface = chromeRemoteInterface(config).then(chromeAPI => chromeAPI).catch(err => { throw err;
}); return Promise.all([chromeInstance, remoteInterface])
}).catch(err => { throw err
}); return wrapperEntry
};
開啟百度,獲取頁面效能資料,參考
const wrapper = require('the-wrapper-module'); const performanceParser = (perforceTiming) => { let timingGather = {};
perforceTiming = perforceTiming || {};
timingGather.redirect = perforceTiming.redirectEnd - perforceTiming.redirectEnd-perforceTiming.redirectStart;
timingGather.dns = perforceTiming.domainLookupEnd - perforceTiming.domainLookupStart;
timingGather.tcp = perforceTiming.connectEnd - perforceTiming.connectStart;
timingGather.request = perforceTiming.responseStart - perforceTiming.requestStart;
timingGather.response = perforceTiming.responseEnd - perforceTiming.responseStart;
timingGather.domReady = perforceTiming.domContentLoadedEventStart - perforceTiming.navigationStart;
timingGather.load = perforceTiming.loadEventStart - perforceTiming.navigationStart; return timingGather;
}; const showPerformanceInfo = (performanceInfo) => {
performanceInfo = performanceInfo || {}; console.log(`頁面重定向耗時:${performanceInfo.redirect}`); console.log(`DNS查詢耗時:${performanceInfo.dns}`); console.log(`TCP連線耗時:${performanceInfo.tcp}`); console.log(`請求傳送耗時:${performanceInfo.request}`); console.log(`響應接收耗時:${performanceInfo.response}`); console.log(`DOMReady耗時:${performanceInfo.domReady}`); console.log(`頁面載入耗時:${performanceInfo.load}`);
};
wrapper.prepareAPI().then(([chromeInstance, remoteInterface]) => { const {Runtime,Page} = remoteInterface;
Page.loadEventFired(() => {
Runtime.evaluate({
expression:'window.performance.timing.toJSON()',
returnByValue:true //不加這個引數,拿到的是一個物件的meta資訊,還需要getProperties }).then((resultObj) => { let {result,exceptionDetails} = resultObj; if(!exceptionDetails){
showPerformanceInfo(performanceParser(result.value))
}else{ throw exceptionDetails;
}
});
});
Page.enable().then(() => {
Page.navigate({
url:'' })
});
});
開啟百度 搜尋Web自動化 headless chrome,並爬取首屏結果連結
const wrapper = require('the-wrapper-module'); //有this的地方寫成箭頭函式要注意,這裡會有問題 const buttonClick = function () { this.click();
}; const setInputValue = () => { var input = document.getElementById('kw');
input.value = 'Web自動化 headless chrome';
}; const parseSearchResult = () => { let resultList = []; const linkBlocks = document.querySelectorAll('div.result.c-container'); for (let block of Array.from(linkBlocks)) { let targetObj = block.querySelector('h3');
resultList.push({
title: targetObj.textContent,
link: targetObj.querySelector('a').getAttribute('href')
});
} return resultList;
};
wrapper.prepareAPI({ // headless: false //加上這行程式碼可以檢視瀏覽器的變化 }).then(([chromeInstance, remoteInterface]) => { const {Runtime, DOM, Page, Network} = remoteInterface; let framePointer;
Promise.all([Page.enable(), Network.enable(), DOM.enable(),Page.setAutoAttachToCreatedPages({autoAttach:true})]).then(() => {
Page.domContentEventFired(() => { console.log('Page.domContentEventFired')
Runtime.evaluate({
expression:`window.location.href`,
returnByValue:true }).then(result => { console.log(result)
})
});
Page.frameNavigated(() => { console.log('Page.frameNavigated')
Runtime.evaluate({
expression:`window.location.href`,
returnByValue:true }).then(result => { console.log(result)
})
})
Page.loadEventFired(() => { console.log('Page.loadEventFired')
Runtime.evaluate({
expression:`window.location.href`,
returnByValue:true }).then(result => { console.log(result)
})
DOM.getDocument().then(({root}) => { //百度首頁表單 DOM.querySelector({
nodeId: root.nodeId,
selector: '#form' }).then(({nodeId}) => {
Promise.all([ //找到 搜尋框填入值 DOM.querySelector({
nodeId: nodeId,
selector: '#kw' }).then((inputNode) => {
Runtime.evaluate({ // 兩種寫法 // expression:'document.getElementById("kw").value = "Web自動化 headless chrome"', expression: `(${setInputValue})()`
}); //這段程式碼不起作用 日狗 // DOM.setNodeValue({ // nodeId:inputNode.nodeId, // value:'Web自動化 headless chrome' // }); //上面的程式碼需求要這麼寫 // DOM.setAttributeValue({ // nodeId:inputNode.nodeId, // name:'value', // value:'headless chrome' // }); }) //找到 提交按鈕setInputValue , DOM.querySelector({
nodeId,
selector: '#su' })
]).then(([inputNode, buttonNode]) => {
Runtime.evaluate({
expression: 'document.getElementById("kw").value',
}).then(({result}) => { console.log(result)
}); return DOM.resolveNode({
nodeId: buttonNode.nodeId
}).then(({object}) => { const {objectId} = object; return Runtime.callFunctionOn({
objectId,
functionDeclaration: `${buttonClick}`
})
});
}).then(() => {
setTimeout(() => {
Runtime.evaluate({
expression: `(${parseSearchResult})()`,
returnByValue: true }).then(({result}) => { console.log(result.value) //百度的URL有加密,需要再請求一次拿到真實URL })
},3e3)
});
})
});
});
Page.navigate({
url: '' }).then((frameObj) => {
framePointer = frameObj
});
})
});
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/20597700/viewspace-2141740/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Web自動化之Headless Chrome概覽WebChrome
- Web自動化之Headless Chrome測試框架整合WebChrome框架
- Web自動化之Headless Chrome開發工具庫WebChrome
- 使用 Headless Chrome 進行自動化測試Chrome
- web自動化測試框架-06 如何快速編寫自動化指令碼Web框架指令碼
- 介面自動化實戰之框架搭建框架
- Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案ServerChrome
- 初探 Headless ChromeChrome
- Selenium自動化實現web自動化-1Web
- Web自動化之瀏覽器啟動Web瀏覽器
- [譯] JavaScript 自動化爬蟲入門指北(Chrome + Puppeteer + Node JS):和 Headless Chrome 一起裝逼一起飛JavaScript爬蟲ChromeJS
- Playwright自動化測試工具之元素定位實戰
- kubebuilder實戰之五:operator編碼UI
- UI自動化測試實戰UI
- java自動化——web自動化複習JavaWeb
- Web自動化-Selenium自動化測試-4-編寫測試用例Web
- 介面自動化測試實戰之智慧場景如何攻破
- 實戰專案之自動簡歷
- 介面自動化測試之PHPUnit-框架程式碼編寫2PHP框架
- py27+selenium+chrome(headless)Chrome
- Chrome實現自動化測試:錄製回放網頁動作Chrome網頁
- 有贊 WEB-UI 自動化實踐WebUI
- UI自動化實戰進階後續UI
- jenkins自動化專案部署實戰Jenkins
- 前端自動化釋出實戰總結前端
- RF-Web自動化Web
- python selenium 用法 和 Chrome headlessPythonChrome
- webpack 學習筆記:實戰之 babel 編碼Web筆記Babel
- Selenium 自動化測試從零實戰
- Chrome 66禁止聲音自動播放之後Chrome
- Appium自動化測試之微信h5元素識別和程式碼實戰APPH5
- 是否只有實現了容器化、自動編排等等才算是實現了運維自動化?運維
- 二、web自動化快速使用Web
- 加速Web自動化測試Web
- Gradle自動化專案構建之Gradle學習及實戰Gradle
- ElasticSearch實戰-編碼實踐Elasticsearch
- Web前端自動化測試Cypress實踐總結Web前端
- iOS自動化編譯打包iOS編譯