node基于puppeteer模擬登錄抓取頁面的實現(xiàn)
關于熱圖
在網(wǎng)站分析行業(yè)中,網(wǎng)站熱圖能夠很好的反應用戶在網(wǎng)站的操作行為,具體分析用戶的喜好,對網(wǎng)站進行針對性的優(yōu)化,一個熱圖的例子(來源于ptengine)
上圖中能很清晰的看到用戶關注點在那,我們不關注產(chǎn)品中熱圖的功能如何,本篇文章就熱圖的實現(xiàn)做一下簡單的分析和總結。
熱圖主流的實現(xiàn)方式
一般實現(xiàn)熱圖顯示需要經(jīng)過如下階段:
1.獲取網(wǎng)站頁面
2.獲取經(jīng)過處理后的用戶數(shù)據(jù)
3.繪制熱圖
本篇主要聚焦于階段1來詳細的介紹一下主流的在熱圖中獲取網(wǎng)站頁面的實現(xiàn)方式
4.使用iframe直接嵌入用戶網(wǎng)站
5.抓取用戶頁面保存到本地,通過iframe嵌入本地資源(所謂本地資源這里認為是分析工具這一端)
兩種方式各有各的優(yōu)缺點
首先第一種直接嵌入用戶網(wǎng)站,這個有一定的限制條件,比如如果用戶網(wǎng)站為了防止iframe劫持,不允許iframe嵌套(設置meta X-FRAME-OPTIONS 為sameorgin 或者直接設置http header ,甚至直接通過js來控制if(window.top !== window.self){ window.top.location = window.location;}
),這種情況下就需要客戶網(wǎng)站做一部分工作才可以被分析工具的iframe加載,使用起來不一定那么方便,因為并不是所有的需要檢測分析的網(wǎng)站用戶都可以管理網(wǎng)站的。
第二種方式,直接抓取網(wǎng)站頁面到本地服務器,然后瀏覽的是本機服務器上抓取的頁面,這種情況下頁面已經(jīng)過來了,我們就可以為所欲為了,首先我們繞過了X-FRAME-OPTIONS 為sameorgin的問題,只需要解決js控制的問題,對于抓取的頁面來說,我們可以通過特殊的對應來處理(比如移除對應的js控制,或者添加我們自己的js);但是這種方式也有很多的不足:1、無法抓取spa頁面,無法抓取需要用戶登錄授權的頁面,無法抓取用戶設置了白明白的頁面等等。
兩種方式都存在https 和 http資源由于同源策略引起的另一個問題,https站無法加載http資源,所以如果為了最好的兼容性,熱圖分析工具需要被應用http協(xié)議,當然具體可以根據(jù)訪問的客戶網(wǎng)站而具體分站優(yōu)化。
抓取網(wǎng)站頁面如何優(yōu)化
這里我們針對抓取網(wǎng)站頁面遇到的問題基于puppeteer做一些優(yōu)化,提高抓取成功的概率,主要優(yōu)化以下兩種頁面:
1.spa頁面
spa頁面在當前頁算是主流了,但是它總所周知的是其對搜索引擎的不友好;通常的頁面抓取程序其實就是一個簡單的爬蟲,其過程通常都是發(fā)起一個http get 請求到用戶網(wǎng)站(應該是用戶網(wǎng)站服務器)。這種抓取方式本身就會有問題問題,首先,直接請求的是用戶服務器,用戶服務器對非瀏覽器的agent 應該會有很多限制,需要繞過處理;其次,請求返回的是原始內容,需要在瀏覽器中通過js渲染的部分無法獲?。ó斎?,在iframe嵌入后,js執(zhí)行還是會再一定程度上彌補這個問題),最后如果頁面是spa頁面,那么此時獲取的只是模板,在熱圖中顯示效果非常不友好。
針對這種情況,如果基于puppeteer來做,流程就變成了
puppeteer啟動瀏覽器打開用戶網(wǎng)站-->頁面渲染-->返回渲染后結果,簡單的用偽代碼實現(xiàn)如下:
const puppeteer = require('puppeteer'); async getHtml = (url) =>{ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); return await page.content(); }
這樣我們拿到的內容就是渲染后的內容,無論頁面的渲染方式如何(客戶端渲染抑或服務端)
需要登錄的頁面
對于需要登錄頁面其實分為多種情況:
需要登錄才可以查看頁面,如果沒有登錄,則跳轉到login頁面(各種管理系統(tǒng))
對于這種類型的頁面我們需要做的就是模擬登錄,所謂模擬登錄就是讓瀏覽器去登錄,這里需要用戶提供對應網(wǎng)站的用戶名和密碼,然后我們走如下的流程:
訪問用戶網(wǎng)站-->用戶網(wǎng)站檢測到未登錄跳轉到login-->puppeteer控制瀏覽器自動登錄后跳轉到真正需要抓取的頁面,可用如下偽代碼來說明:
const puppeteer = require("puppeteer"); async autoLogin =(url)=>{ const browser = await puppeteer.launch(); const page =await browser.newPage(); await page.goto(url); await page.waitForNavigation(); //登錄 await page.type('#username',"用戶提供的用戶名"); await page.type('#password','用戶提供的密碼'); await page.click('#btn_login'); //頁面登錄成功后,需要保證redirect 跳轉到請求的頁面 await page.waitForNavigation(); return await page.content(); }
登錄與否都可以查看頁面,只是登錄后看到內容會所有不同 (各種電商或者portal頁面)
這種情況處理會比較簡單一些,可以簡單的認為是如下步驟:
通過puppeteer啟動瀏覽器打開請求頁面-->點擊登錄按鈕-->輸入用戶名和密碼登錄 -->重新加載頁面
基本代碼如下圖:
const puppeteer = require("puppeteer"); async autoLoginV2 =(url)=>{ const browser = await puppeteer.launch(); const page =await browser.newPage(); await page.goto(url); await page.click('#btn_show_login'); //登錄 await page.type('#username',"用戶提供的用戶名"); await page.type('#password','用戶提供的密碼'); await page.click('#btn_login'); //頁面登錄成功后,是否需要reload 根據(jù)實際情況來確定 await page.reload(); return await page.content(); }
總結
明天總結吧,今天下班了。
補充(還昨天的債):基于puppeteer雖然可以很友好的抓取頁面內容,但是也存在這很多的局限
1.抓取的內容為渲染后的原始html,即資源路徑(css、image、javascript)等都是相對路徑,保存到本地后無法正常顯示,需要特殊處理(js不需要特殊處理,甚至可以移除,因為渲染的結構已經(jīng)完成)
2.通過puppeteer抓取頁面性能會比直接http get 性能會差一些,因為多了渲染的過程
3.同樣無法保證頁面的完整性,只是很大的提高了完整的概率,雖然通過page對象提供的各種wait 方法能夠解決這個問題,但是網(wǎng)站不同,處理方式就會不同,無法復用。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Node.JS發(fā)送http請求批量檢查文件中的網(wǎng)頁地址、服務是否有效可用
這篇文章主要介紹了Node.JS發(fā)送http請求批量檢查文件中的網(wǎng)頁地址、服務是否有效可用,本文通過實例代碼文字說明給大家講解的非常詳細,需要的朋友參考下2019-11-11Node.js和Express中設置TypeScript的實現(xiàn)步驟
本文主要介紹了Node.js和Express中設置TypeScript的實現(xiàn)步驟文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-11-11Node.js中環(huán)境變量process.env的一些事詳解
這篇文章主要給大家介紹了關于Node.js中環(huán)境變量process.env的一些事,文中通過示例代碼介紹的非常詳細,對大家學習或者使用node.js具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-10-10