使用Puppeteer實(shí)現(xiàn)頁面遍歷的示例代碼
前言
很多時(shí)候我們需要遍歷我們的頁面來檢查頁面是否存在問題,以更好的保證可用性和安全性,所以遍歷一個(gè)給定頁面是比較通用的能力,是很多高級(jí)功能的基礎(chǔ)。下面就介紹怎么使用puppeteer來實(shí)現(xiàn)頁面遍歷的功能。
基本算法
實(shí)現(xiàn)頁面的遍歷功能,我們需要實(shí)現(xiàn)幾個(gè)基礎(chǔ)的方法,如下:
- 怎么獲取到登錄態(tài)
- 頁面如何打開
- 獲取到頁面的可點(diǎn)擊節(jié)點(diǎn)
- 頁面的滑動(dòng),點(diǎn)擊,截圖等基礎(chǔ)功能
- 頁面請(qǐng)求的攔截,識(shí)別
- 頁面返回/退出
上述能力實(shí)現(xiàn)之后,將他們組合起來,就可以實(shí)現(xiàn)一個(gè)頁面的遍歷功能,我們分別講解每個(gè)功能如何實(shí)現(xiàn)。
功能實(shí)現(xiàn)

登錄態(tài)
不同的帳號(hào)有不同的登錄方式,最通用的就是專門寫一個(gè)腳本來實(shí)現(xiàn)登錄功能。對(duì)于需要掃碼登錄的頁面,其實(shí)是從服務(wù)端獲取登錄token,可以直接調(diào)用服務(wù)端來獲?。ㄇ疤崾悄阕约旱臉I(yè)務(wù))。否則就只能老老實(shí)實(shí)的通過腳本來實(shí)現(xiàn)了(在瀏覽器端實(shí)現(xiàn)腳本相對(duì)容易)。
頁面打開
puppeteer提供了專門的方法來打開頁面,我們只要初始化之后,調(diào)用這個(gè)功能就可以了。代碼如下:
async function openUrl( targetUrl ){
//const browser = await puppeteer.connect(config.browserLaunchOptions);
const browser = await puppeteer.launch(config.browserLaunchOptions);
console.log("userAgent:"+JSON.stringify(await browser.userAgent()));
const page = await browser.newPage();
interactor(page)
/**
* 開啟監(jiān)聽頁面請(qǐng)求數(shù)據(jù)
*/
await setPageWatcher(page);
await page.emulate(config.pageEmulateOptions);
await page.goto(targetUrl, {timeout:config.timeoutMillSeconds, waitUntil: config.waitUntilStr}).catch(err => {});
await page.waitFor(10000);
await waitForPageComplete(page,2);
await setBrowserWatcher(browser);
loginPageUrl = targetUrl;
return page;
}獲取頁面的可點(diǎn)擊點(diǎn)
拿到一個(gè)頁面之后我們需要獲取到他可點(diǎn)擊的點(diǎn)位信息,以便我們后續(xù)遍歷的時(shí)候操作,所以需要一個(gè)獲取頁面可點(diǎn)擊點(diǎn)的方法。實(shí)現(xiàn)如下:
async function getClickableElements( targetFrame ){
try{
let sections = await targetFrame.$$('[data-clickable=true],.tr-tabbar-item')
return sections;
} catch (e) {
console.log(e);
return null;
}
}頁面的滑動(dòng),點(diǎn)擊,截圖等基礎(chǔ)功能
對(duì)于頁面的滑動(dòng),點(diǎn)擊和截圖,有專門的方法來實(shí)現(xiàn),代碼如下:
function screenshot( page,picName ){
return new Promise((resolve, reject) => {
setTimeout(async () => {
var newPage=null;
try {
var buf=null;
if( newPagePromise ){
console.log('新開了一個(gè)頁面');
newPage = await newPagePromise;
await newPage.waitFor(6000);
var currentUrl=await newPage.url();
console.log("new-Page-Url:"+currentUrl);
if(currentUrl&¤tUrl.includes('https://login.xxx.com/login.htm?redirectURL=')){
currentUrl = currentUrl.replace('https://login.xxx.com/login.htm?redirectURL=',config.loginUrl);
console.log("newUrl="+currentUrl);
await openTargetUrl(newPage,currentUrl);
}
buf = await newPage.screenshot({
})
await newPage.close();
newPagePromise = null;
await page.bringToFront();
} else {
buf = await page.screenshot({
})
}
if(buf){
console.log('截圖完成,開始上傳');
var picUrl =await util.uploadImageWithRetry(picName,buf);
console.log("截圖成功:"+picUrl);
resolve(picUrl)
}
resolve(null);
} catch (e) {
if (newPage) {
await newPage.close();
}
newPagePromise = null;
await page.bringToFront();
console.log(e);
reject(null)
}
})
})
}
// 元素點(diǎn)擊
await element.tap(2000);頁面請(qǐng)求的攔截,識(shí)別
在執(zhí)行過程中頁面可能出現(xiàn)跳轉(zhuǎn),并且我們還需要監(jiān)聽頁面的請(qǐng)求來檢查是不是正常。實(shí)現(xiàn)如下:
function setPageWatcher(page) {
page.on('requestfailed', error => {
if(error.url()&&error.url().includes('https://login.xxx.com')){
console.log("跳轉(zhuǎn)到了登錄頁面:"+error);
needReLogin = true;
}
})
page.on('error', (error) => {
//console.log(chalk.red('?? whoops! there was an error'))
//console.log(error)
})
page.on('pageerror', (error) => {
//console.log(error)
})
page.on('response',(response) => {
if( "image"==response.request().resourceType() && response.url() && response.headers()['content-length'] && response.headers()['content-length'] >200 ){
allResource.push({
size: response.headers()['content-length'],
type: response.request().resourceType(),
url: response.url()
});
}
})
page.on('dialog', async dialog => {
console.log("dialog");
await dialog.accept();
console.log(dialog.message());
//await dialog.dismiss();
});
}頁面返回/退出
代碼如下:
function pageBack( page, frameInfo,num ){
??????? console.log("開始回到首頁");
return new Promise((resolve, reject) => {
setTimeout(async () => {
try {
let backIcons = await frameInfo.backIconFrame.$$('.backIcon');
if(backIcons.length>0&&!needReLogin){
try{
console.log("回到首頁");
await backIcons[0].tap(2000);
await page.waitFor(2000);
resolve(frameInfo);
}catch (e) {
resolve(reloadPage(page,num));
}
} else {
resolve(reloadPage(page,num));
}
} catch (e) {
console.log('回到首頁出錯(cuò)!',e);
resolve(reloadPage(page,num))
}
})
})
}以上基本功能就實(shí)現(xiàn)了,歡迎交流
以上就是使用Puppeteer實(shí)現(xiàn)頁面遍歷的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Puppeteer頁面遍歷的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Node.js中fs模塊實(shí)現(xiàn)配置文件的讀寫操作
在Node.js中, fs模塊提供了對(duì)文件系統(tǒng)的訪問功能,我們可以利用它來實(shí)現(xiàn)配置文件的讀取和寫入操作,這篇文章主要介紹了Node.js中fs模塊實(shí)現(xiàn)配置文件的讀寫,需要的朋友可以參考下2024-04-04
Vue+Node服務(wù)器查詢Mongo數(shù)據(jù)庫及頁面數(shù)據(jù)傳遞操作實(shí)例分析
這篇文章主要介紹了Vue+Node服務(wù)器查詢Mongo數(shù)據(jù)庫及頁面數(shù)據(jù)傳遞操作,結(jié)合實(shí)例形式分析了node.js查詢MongoDB數(shù)據(jù)庫及vue前臺(tái)頁面渲染等相關(guān)操作技巧,需要的朋友可以參考下2019-12-12
nodejs對(duì)express中next函數(shù)的一些理解
這篇文章主要介紹了nodejs對(duì)express中next函數(shù)的一些理解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
使用Node.js實(shí)現(xiàn)base64和png文件相互轉(zhuǎn)換的方法
這篇文章主要介紹了使用Node.js實(shí)現(xiàn)base64和png文件相互轉(zhuǎn)換的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
node.js使用express-fileupload中間件實(shí)現(xiàn)文件上傳
本文使用express作為服務(wù)端,使用express-fileupload庫提供的中間件函數(shù)來接受從客戶端傳來的圖片,并將圖片作為文件存儲(chǔ)在服務(wù)端,感興趣的可以了解一下2021-07-07
nodejs獲取微信小程序帶參數(shù)二維碼實(shí)現(xiàn)代碼
這篇文章主要介紹了nodejs獲取微信小程序帶參數(shù)二維碼實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04

