0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

網(wǎng)頁爬蟲 JavaScript 頁面渲染技術(shù)與應(yīng)用

電子設(shè)計(jì) ? 來源:電子設(shè)計(jì) ? 作者:電子設(shè)計(jì) ? 2020-12-25 18:28 ? 次閱讀

廖雨寒 楊彥松 張斌

睿哲科技股份有限公司

一、背景

隨著網(wǎng)絡(luò)的迅速發(fā)展,萬維網(wǎng)成為大量信息的載體,如何有效地提取并利用這些信息成為一個(gè)巨大的挑戰(zhàn),網(wǎng)絡(luò)爬蟲(web crawler)隨之而生。但是現(xiàn)在的網(wǎng)站很少有純靜態(tài)網(wǎng)頁,大部分網(wǎng)站都通過JavaScript渲染、ajax異步等實(shí)現(xiàn)網(wǎng)頁數(shù)據(jù)加載。對于目前的爬蟲框架來說,基本都是爬取到的未渲染過的HTML源碼,所以對于爬蟲來說沒真正做到瀏覽器的所見即所爬。對于scrapy來說,官方有一個(gè)scrapy-splash項(xiàng)目支持頁面渲染解析,然而scrapy-splash在高并發(fā)狀態(tài)下極其不穩(wěn)定。一種方案是通過webkit瀏覽器引擎直接渲染,另一種方案是通過調(diào)用瀏覽器渲染。通過幾種方案比較,最終選擇了Google Chrome Devtools Protocol開發(fā)渲染功能。

二、渲染方案可行性分析

1.Scrapy-Splash

Scrapy-splash是scrapy官方團(tuán)隊(duì)提供的一個(gè)解決js渲染問題的方案。Splash是處理網(wǎng)頁渲染的模塊,它內(nèi)部使用的開源的webkit瀏覽器引擎,通過HTTP API來使用渲染服務(wù)。在scrapy中通過DownloaderMiddleware處理網(wǎng)頁請求,實(shí)際是去請求splash接口并得到渲染后的數(shù)據(jù)。

Splash優(yōu)點(diǎn):

可以并行處理多個(gè)網(wǎng)頁

獲取HTML結(jié)果和/或截取屏幕截圖

關(guān)掉加載圖片或使用 Adblock Plus規(guī)則使得渲染速度更快

使用JavaScript處理網(wǎng)頁內(nèi)容

使用Lua腳本

能夠獲得具體的HAR格式的渲染信息

然而在實(shí)際使用scrapy-splash的過程中,也遇到過一些splash的問題:

對于一些特殊網(wǎng)站,并不能很好的處理重定向,比如一些需要通過js渲染Cookie的頁面,需要通過location對象重定向好幾次才能到真正的頁面,但是splash只是處理了第一次的渲染Cookie后并沒有實(shí)現(xiàn)跳轉(zhuǎn)

在并發(fā)的情況下,獲取到的數(shù)據(jù)有時(shí)候是沒有內(nèi)容的

2.Scrapy-QtWebkit

Splash是采用Webkit引擎實(shí)現(xiàn)的網(wǎng)頁渲染,可直接采用Webkit對接Scrapy實(shí)現(xiàn)渲染網(wǎng)頁。在Qt庫中有相應(yīng)的QtWebkit模塊,但是在Qt5.6版本以上QtWebkit就被淘汰了,代替它的是QtWebEngine,因此,選擇QtWebKit時(shí),建議使用Qt4或者Qt5.6之前的版本。

Webkit大致通過View-->Page-->Frame的流程來加載網(wǎng)頁。通過這些模塊,對于上面splash遇到重定向問題和空頁面問題都能得到解決。

Webkit優(yōu)點(diǎn):

細(xì)粒度處理網(wǎng)頁渲染

資源加載可控

直接交與webkit處理更效率

Webkit缺點(diǎn):

內(nèi)存資源占用較大

高并發(fā)處理網(wǎng)頁過多容易引起C底層錯(cuò)誤

三、Google Chrome Devtools Protocol

以上兩種方案,都存在各自的缺點(diǎn), 那有沒有可能直接通過調(diào)用瀏覽器加載網(wǎng)頁呢?事實(shí)上selenium可以操作瀏覽器。selenium操作chrome是使用chromedriver,chromedriver底層應(yīng)用的是Chrome Devtools Protocol,因此,何不直接使用Chrome Devtools Protocol。

Chrome Devtools Protocol介紹

在Chrome/Chromium瀏覽器中,按F12會彈出調(diào)試工具,它是通過Chrome Devtools Protocol的協(xié)議來進(jìn)行數(shù)據(jù)通訊。Chrome Devtools Protocol用來與瀏覽器頁面(pages)交互和調(diào)試的協(xié)議通道。它采用websocket來與頁面建立通信通道,由發(fā)送給頁面的Commands和它所產(chǎn)生的Events組成。

在Chrome Devtools Protocol中,有很多不同的功能模塊域(domains),類似于Chrome開發(fā)這工具的個(gè)功能模塊。

然而對于此例的爬蟲來說,只需要用到Network,Page,Runtime等幾個(gè)功能模塊域:

Network允許跟蹤頁面的網(wǎng)絡(luò)活動(dòng),它公開http, file, data,網(wǎng)絡(luò)請求和響應(yīng)等數(shù)據(jù)信息

Page會檢查與頁面相關(guān)的動(dòng)作和事件

Runtime主要用作運(yùn)行JavaScript操作代碼

啟動(dòng)調(diào)試實(shí)例

要使用Chrome Devtools Protocol,需要開啟調(diào)試。我們的項(xiàng)目運(yùn)行在服務(wù)器中,所以需要開啟無頭模式 --h(huán)eadless --disable-gpu --no-sandbox。

chrome.exe --remote-debugging-port=9222 --h(huán)eadless --disable-gpu --no-sandbox

如果需要遠(yuǎn)程調(diào)試,可以加上參數(shù)--remote-debugging-address='0.0.0.0'。

操作Chrome Devtools Protocol

通過以上命令可以啟動(dòng)一個(gè)Chrome調(diào)試實(shí)例,通過HTTP調(diào)用接口:

http://loacalhost:9222/json

會得到接口返回的JSON數(shù)據(jù):

"description": "",

"devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/A6C1F7B23DFF222A87143ACB37CBF7C4",

"id": "A6C1F7B23DFF222A87143ACB37CBF7C4",

"title": "about:blank",

"type": "page",

"url": "about:blank",

"webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/A6C1F7B23DFF222A87143ACB37CBF7C4"

默認(rèn)開啟實(shí)例后會有一個(gè)空的標(biāo)簽頁(Tab),要?jiǎng)?chuàng)建新的Tab,只需要通過調(diào)用接口

http://loacalhost:9222/json/new

或者在后面直接添加網(wǎng)址,Tab將會創(chuàng)建并加載網(wǎng)頁

http://loacalhost:9222/json/new?http://www.example.com/

在每個(gè)Tab中有一個(gè)webSocketDebuggerUrl字段,它提供了一個(gè)WebSocket接口與Chrome交互。比如要啟用Page模塊域,通過WebSocket發(fā)送以下命令開啟:

{"id":1, "method":"Page.enable", "params":{}}

關(guān)閉Tab

http://loacalhost:9222/json/close/A6C1F7B23DFF222A87143ACB37CBF7C4

四、Scrapy實(shí)現(xiàn)Chrome Protocol下載渲染頁面

Scrapy是一個(gè)爬蟲框架,它使用了Twisted異步網(wǎng)絡(luò)庫來處理網(wǎng)絡(luò)通訊,他的大致架構(gòu)流程如圖

圖 1 Scrapy框架

在圖1中我們看到scrapy處理網(wǎng)絡(luò)請求的是Downloader模塊,他通過DownloaderHandler下載處理器完成下載網(wǎng)絡(luò)請求,下載處理器使用的是Twisted網(wǎng)絡(luò)庫實(shí)現(xiàn)的,對于Chrome Protocol來說我們通過接口操作命令實(shí)現(xiàn)網(wǎng)頁加載本質(zhì)上是Chrome加載網(wǎng)頁,也就是說下載處理是通過Chrome Protocol接口操作Chrome瀏覽器請求加載并渲染網(wǎng)頁,因此我們需要拿到渲染后的網(wǎng)頁HTML源碼,需要改寫DownloaderHandler。

然而原生操作Chrome Protocol太繁瑣,我們需要封裝它。在Github上有多種語言實(shí)現(xiàn)了Chrome Devtools Protocol的封裝。對于Python來說,我們使用Pychrome庫來操作Chrome Protocol,可以直接用pip安裝模塊:

pip install pychrome

當(dāng)然要使用該模塊得要啟動(dòng)Chrome調(diào)試實(shí)例,通過實(shí)例的地址和端口號連接:

browser = pychrome.Browser(url="http://<your_ip>:9222")

通過new_tab()方法創(chuàng)建tab標(biāo)簽頁,通過tab.start()啟動(dòng)當(dāng)前tab的websocket鏈接,例如需要啟動(dòng)Network功能域,通過調(diào)用tab.Network.enable()來啟動(dòng),通過tab.Page.navigate(url="http://www.example.com")加載網(wǎng)頁,該頁面加載時(shí)的一切網(wǎng)絡(luò)活動(dòng)都可以通過接收websocket響應(yīng)得到j(luò)son數(shù)據(jù)。

這時(shí)會有一個(gè)問題,何時(shí)才算是真正渲染完成頁面?

圖 2 JS渲染流程

在圖2中是瀏覽器從輸入網(wǎng)址到頁面加載完成的處理流程,loadEventEnd是真正加載完成,但是在一些使用ajax異步請求的網(wǎng)頁使用loadEventEnd并不能很好的判斷為渲染結(jié)束,所以這里我們使用JavaScript命令獲取readyState狀態(tài)判斷頁面是否加載完成:

document.readyState

readyState一共有五種狀態(tài):

uninitialized - XML 對象被產(chǎn)生,但沒有任何文件被加載

loading - 加載程序進(jìn)行中,但文件尚未開始解析

loaded - 部分的文件已經(jīng)加載且進(jìn)行解析,但對象模型尚未生效

interactive - 僅對已加載的部分文件有效,在此情況下,對象模型是有效但只讀的

complete - 文件已完全加載,代表加載成功

通過document.readyState == complate來判斷數(shù)據(jù)的加載進(jìn)度。當(dāng)加載完成時(shí)通過javascript命令獲取渲染后的HTML源碼:

document.documentElement.outerHTML

在這里我們就可以使用Pychrome替代scrapy的twisted下載處理。

五、結(jié)語

使用chrome devtools protocol來操作chrome瀏覽器來渲染頁面,能基本完成渲染頁面的需求,一些需要與瀏覽器交互的頁面也大致能使用JavaScript操作命令,重點(diǎn)是使用chrome操作頁面渲染會很占用資源,因此不宜過多的開啟渲染進(jìn)程,多線程下載盡量重用Tab標(biāo)簽頁,因?yàn)槊慷鄤?chuàng)建一個(gè)Tab相當(dāng)于開了一個(gè)進(jìn)程,最后,爬蟲結(jié)束時(shí),應(yīng)該調(diào)用相關(guān)接口關(guān)閉所有Tab,釋放資源。

審核編輯:符乾江
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • javascript
    +關(guān)注

    關(guān)注

    0

    文章

    515

    瀏覽量

    53717
  • 應(yīng)用軟件
    +關(guān)注

    關(guān)注

    0

    文章

    49

    瀏覽量

    9067
收藏 人收藏

    評論

    相關(guān)推薦

    爬蟲的基本工作原理 用Scrapy實(shí)現(xiàn)一個(gè)簡單的爬蟲

    數(shù)以萬億的網(wǎng)頁通過鏈接構(gòu)成了互聯(lián)網(wǎng),爬蟲的工作就是從這數(shù)以萬億的網(wǎng)頁中爬取需要的網(wǎng)頁,從網(wǎng)頁中采集內(nèi)容并形成結(jié)構(gòu)化的數(shù)據(jù)。
    的頭像 發(fā)表于 12-03 11:45 ?1439次閱讀
    <b class='flag-5'>爬蟲</b>的基本工作原理 用Scrapy實(shí)現(xiàn)一個(gè)簡單的<b class='flag-5'>爬蟲</b>

    javascript屬于前端嗎

    JavaScript是一種高級編程語言,通常用于網(wǎng)頁開發(fā)。它是一種腳本語言,可用于在網(wǎng)頁上動(dòng)態(tài)交互,提供更好的用戶體驗(yàn)。JavaScript是一種廣泛使用的
    的頭像 發(fā)表于 12-03 11:43 ?1328次閱讀

    javascript規(guī)定了幾種語言類型

    JavaScript是一種強(qiáng)大的編程語言,主要用于在網(wǎng)頁上實(shí)現(xiàn)動(dòng)態(tài)的交互效果和功能。它不僅可以與HTML和CSS配合使用來構(gòu)建網(wǎng)頁,還可以用于開發(fā)各種類型的應(yīng)用程序,包括網(wǎng)絡(luò)應(yīng)用程序、桌面應(yīng)用程序
    的頭像 發(fā)表于 12-03 11:37 ?705次閱讀

    javascript的變量中可以包含

    JavaScript是一種強(qiáng)大的編程語言,廣泛應(yīng)用于網(wǎng)頁開發(fā)和動(dòng)態(tài)網(wǎng)頁交互。作為一種靈活的語言,JavaScript允許開發(fā)人員聲明和操作各種類型的變量。在
    的頭像 發(fā)表于 12-03 11:34 ?651次閱讀

    javascript語言的用途

    JavaScript是一種高級編程語言,常用于為網(wǎng)頁添加交互性和動(dòng)態(tài)功能。它是一種客戶端腳本語言,可以通過瀏覽器執(zhí)行。雖然它最初是用于處理網(wǎng)頁上的簡單任務(wù),但現(xiàn)在它已經(jīng)提供了許多強(qiáng)大的功能,可以用
    的頭像 發(fā)表于 12-03 11:30 ?644次閱讀

    javascript基于什么的語言

    瀏覽器上運(yùn)行的腳本語言,用來增強(qiáng)網(wǎng)頁的交互性和動(dòng)態(tài)性。最初的JavaScript被命名為LiveScript,但后來在與Sun公司合作推出Java后,為了借用Java的聲望,Netscape將其更名
    的頭像 發(fā)表于 12-03 11:28 ?1008次閱讀

    JavaScript的語法和基本功能

    JavaScript(簡稱JS)是一種常用的腳本編程語言,廣泛應(yīng)用于網(wǎng)頁開發(fā)、移動(dòng)應(yīng)用開發(fā)等領(lǐng)域。正式的JS標(biāo)準(zhǔn)由Ecma國際組織制定并維護(hù),最新的ECMAScript標(biāo)準(zhǔn)定義了JavaScript
    的頭像 發(fā)表于 12-03 11:15 ?546次閱讀

    怎樣開啟javascript功能

    JavaScript是一種客戶端腳本語言,它可以在網(wǎng)頁中實(shí)現(xiàn)動(dòng)態(tài)交互和功能增強(qiáng)。在現(xiàn)代網(wǎng)頁開發(fā)中,幾乎所有的瀏覽器都支持JavaScript,因此,開啟
    的頭像 發(fā)表于 12-03 11:13 ?3313次閱讀

    JavaScript的用途和功能

    開發(fā)中發(fā)揮著非常重要的作用,并為用戶提供了更為豐富的使用體驗(yàn)。下面我們將詳細(xì)討論JavaScript的用途和功能。 首先,JavaScript用于網(wǎng)頁開發(fā)中的動(dòng)態(tài)內(nèi)容。通過使用JavaScri
    的頭像 發(fā)表于 12-03 11:12 ?794次閱讀

    javascript指什么

    JavaScript是一種高級編程語言,通常用于為網(wǎng)頁添加交互功能。它是一種面向?qū)ο蟮恼Z言,旨在通過編寫代碼來控制網(wǎng)頁的行為,使用戶能夠與網(wǎng)頁進(jìn)行動(dòng)態(tài)交互。
    的頭像 發(fā)表于 12-03 11:11 ?791次閱讀

    瀏覽器怎么打開javascript

    瀏覽器是一種用于瀏覽和訪問互聯(lián)網(wǎng)頁面的應(yīng)用程序,而JavaScript是一種常用的網(wǎng)頁編程語言,用于給網(wǎng)頁添加交互和動(dòng)態(tài)效果。本文將詳細(xì)探討如何在瀏覽器中打開
    的頭像 發(fā)表于 11-26 11:25 ?2250次閱讀

    瀏覽器支持javascript怎么設(shè)置

    JavaScript之間的關(guān)系。瀏覽器是一個(gè)軟件應(yīng)用程序,用于解析和渲染網(wǎng)頁。它可以是桌面應(yīng)用程序(例如Chrome,F(xiàn)irefox和Safari)或移動(dòng)應(yīng)用程序(例如Safari和Chrome
    的頭像 發(fā)表于 11-26 11:22 ?1320次閱讀

    javascript可以關(guān)閉嗎

    **JavaScript是一種編程語言,它不能被“關(guān)閉”。**JavaScript是一種客戶端腳本語言,它通常嵌入在HTML頁面中。當(dāng)用戶訪問一個(gè)包含JavaScript
    的頭像 發(fā)表于 11-16 10:20 ?1302次閱讀

    javascript有什么用

    JavaScript是一種廣泛使用的編程語言,主要用于增強(qiáng)網(wǎng)頁和創(chuàng)建動(dòng)態(tài)網(wǎng)頁內(nèi)容。以下是JavaScript的一些主要用途: 交互性:JavaScr
    的頭像 發(fā)表于 11-16 10:19 ?882次閱讀

    如何看待Python爬蟲的合法性?

    Python爬蟲是一種自動(dòng)化程序,可以從互聯(lián)網(wǎng)上獲取信息并提取數(shù)據(jù)。通過模擬網(wǎng)頁瀏覽器的行為,爬蟲可以訪問網(wǎng)頁、抓取數(shù)據(jù)、解析內(nèi)容,并將其保存到本地或用于進(jìn)一步分析
    的頭像 發(fā)表于 11-14 10:35 ?530次閱讀