0.引言
由於在軟件工程綜合實踐專題課程中,老師要求在博客園發表博客我自己做過的小項目,本博客為課程第一篇博客
本項目來源於寒假學習python網絡爬蟲時所做的實戰小項目,經過精心挑選,選擇了頁面動態渲染這個話題
1.工具
語言:python3.7,Lua
編譯器:pycharm
包管理工具:pip
工具:Scrapy-Splash
應用容器引擎:docker(需要翻牆),可自行網上百度安裝和配置教程
2. 功能介紹
利用Splash,我們可以實現如下功能:
異步方式處理多個網頁渲染過程;
獲取渲染后的頁面的源代碼或截圖;
通過關閉圖片渲染或者使用Adblock規則來加快頁面渲染速度;
可執行特定的JavaScript腳本;
可通過Lua腳本來控制頁面渲染過程;
獲取渲染的詳細過程並通過HAR(HTTP Archive)格式呈現。
3. 項目實戰
首先,在本機端口運行Splash服務,打開http://localhost:8050/
在輸入框內輸入https://www.shou.edu.cn/,然后點擊Render me
可以看到,網頁的返回結果呈現了渲染截圖、HAR加載統計數據、網頁的源代碼。
通過HAR的結果可以看到,Splash執行了整個網頁的渲染過程,包括CSS、JavaScript的加載等過程,呈現的頁面和瀏覽器中得到的結果完全一致。
4. Splash Lua腳本
Splash是通過Lua腳本來控制了頁面的加載過程的,然后執行一系列渲染操作。
入口及返回值
function main(splash, args) splash:go("https://www.shou.edu.cn/") splash:wait(1) #等待時間 local title = splash:evaljs("document.title") #需要對頁面前端代碼進行分析 return {title=title} end
本代碼通過evaljs()方法傳入JavaScript腳本,而document.title的執行結果就是返回網頁標題,執行完畢后將其賦值給一個title變量,隨后將其返回。
異步處理 ———涉及對多個頁面進行分析比較
function main(splash, args) local example_urls = {"https://www.shou.edu.cn/", "http://www.gdou.edu.cn/", "http://www.ouc.edu.cn/"} local urls = args.urls or example_urls local results = {} for index, url in ipairs(urls) do
local ok, reason = splash:go("http://" .. url) if ok then splash:wait(2) results[url] = splash:png() end
end
return results end
在腳本內調用的wait()方法類似於Python中的sleep(),其參數為等待的秒數。當Splash執行到此方法時,它會轉而去處理其他任務,然后在指定的時間過后再回來繼續處理。
更多Lua腳本的語法詳見http://www.runoob.com/lua/lua-basic-syntax.html
5. Splash對象屬性 ——方法中的對象屬性
args
該屬性可以獲取加載時配置的參數,比如URL,如果為GET請求,它還可以獲取GET請求參數;如果為POST請求,它可以獲取表單提交的數據。
function main(splash, args) local url = args.url end
第二個參數args就相當於splash.args屬性
js_enabled
這個屬性是Splash的JavaScript執行開關,可以將其配置為true或false來控制是否執行JavaScript代碼,默認為true。
function main(splash, args) splash:go("https://www.shou.edu.cn/") splash.js_enabled = false
local title = splash:evaljs("document.title") return {title=title} end
更多對象如resource_timeout、images_enabled、plugins_enabled、scroll_position詳見https://blog.csdn.net/weixin_38239050/article/details/82584613
6. Splash對象的方法
詳見https://splash.readthedocs.io/en/stable/scripting-ref.html
7. Splash API調用
詳見https://splash.readthedocs.io/en/stable/scripting-element-object.html
8. 配置Splash服務
要搭建Splash負載均衡,首先要有多個Splash服務。假如多台遠程主機的都開啟了Splash服務,它這幾個服務必須完全一致,都是通過Docker的Splash鏡像開啟的。訪問其中任何一個服務時,都可以使用Splash服務。
9. 配置負載均衡
選用任意一台帶有公網IP的主機來配置負載均衡。首先,在這台主機上裝好Nginx,然后修改Nginx的配置文件nginx.conf,添加各台主機的ip。
10. 配置認證
現在Splash是可以公開訪問的,如果不想讓其公開訪問,還可以配置認證,這仍然借助於Nginx。 (Nginx為服務器代理服務)
http {
upstream splash {
least_conn;
server xxx; ——xxx為服務器ip地址
server xxx;
……
}
server {
listen 8050;
location / {
proxy_pass http://splash;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
}
}
}
11. 測試
import requests from urllib.parse import quote import re lua = ''' function main(splash, args) local treat = require("treat") local response = splash:http_get("https://www.shou.edu.cn/") return treat.as_string(response.body) end ''' url = 'http://splash:8050/execute?lua_source=' + quote(lua) response = requests.get(url, auth=('admin', 'admin')) ip = re.search('(\d+\.\d+\.\d+\.\d+)', response.text).group(1) print(ip)
這里URL中的splash字符串請自行替換成自己的Nginx服務器IP。這里我修改了Hosts,設置了splash為Nginx服務器IP。
12.心得體會
之前有過屬於自己的Github和CSDN博客,很高興由於有了這門課可以繼續養成發博客的愛。雖然這次作業做的時間比較長,困難比較大,但通過這一不斷摸索的過程,自己學會了許多知識。
我們這學期剛開設 軟件測試這門課程,盡管不知道寫的准確不准確,但是也了解到了測試用例的必備要素和一些規范的寫法。由於長期接觸python,學習了python多個領域,希望可以繼續分享經驗,並且通過這次作業,學會了不少東西。更主要的是,可以更進一步對自己這方面知識的理解。
通過本項目,我對於Javascrip有了更深一步的了解,對於前端代碼有了進一步的認識,服務器配置方面,因只有單台服務器,只能單看教程無法做出新的體會。
本項目對於Lua腳本語言只是冰山一角,本文也是一個拋磚引玉,最主要的還是記錄我自己學習過程,通過實戰不斷鍛煉自己。
13.源代碼
https://github.com/zyhang8/Web-Crawler-Development/tree/master/%E5%8A%A8%E6%80%81%E6%B8%B2%E6%9F%93%E9%A1%B5%E9%9D%A2%E7%88%AC%E5%8F%96/Splash%E7%9A%84%E4%BD%BF%E7%94%A8
14.附
本博客只是基於Splash的強大渲染性能對其進行學習理解,其中的代碼是源於崔老師的實戰對其分析進行理解后自己做的一些小改變。
此博客為第一次編寫因稍有欠缺,但對此作業花費了很多時間和精力,望有個好分數。。。
2019.03.02
希望可以與我多多分享經驗,有空必回