一、Splash 的使用
Splash 是一個JavaScript 渲染服務,帶有 HTTP API的輕量級瀏覽器,同時對接了 Python 中的 Twisted 和 QT 庫。利用它,同樣可以實現動態渲染頁面的抓取。
- 實例引入
- 通過 Splash 提供的 Web 頁面來測試其渲染過程。例:在本機 8050 端口上運行 Splash 服務,打開 http://localhost:8050/ 即可看到其 Web 頁面:
- 黑色框顯示的是一個渲染示例。上方有個輸入框,默認是 http://google.com, 換成百度測試,將內容更改為 https://www.baidu.com,點擊 Render me 按鈕開始渲染。 結果:
- 網頁的返回結果呈現了渲染截圖、HAR 加載統計數據、網頁的源代碼。
- 通過 HAR 的結果可以看到,Splash 執行整個網頁的渲染過程,包括 CSS、JavaScript 的加載等過程,呈現的頁面和瀏覽器中得到的結果完全一致。
- 這個過程由什么來控制呢?重新返回首頁,可以看到有段腳本,內容:
function main(splash, args) assert(splash:go(args.url)) assert(splash:wait(0.5)) return { html = splash:html(), png = splash:png(), har = splash:har(), } end
這個腳本是用 Lua 語言寫的腳本。從腳本的表面意思,它首先調用 go()方法去加載頁面,再調用 wait()方法等待一定時間,最后返回頁面的源碼、截圖和 HAR 信息。
- Splash 通過 Lua 腳本來控制了頁面加載過程,加載過程完全模擬瀏覽器,最后可返回各種格式的結果,如:網頁源碼和截圖等。
- 通過 Splash 提供的 Web 頁面來測試其渲染過程。例:在本機 8050 端口上運行 Splash 服務,打開 http://localhost:8050/ 即可看到其 Web 頁面:
- Splash Lua腳本
- Splash 可以通過 Lua 腳本執行一系列渲染操作,這樣就可以用 Splash 來模擬類似 Chrome、PhantomJS 的操作了。(Splash Lua 腳本的人口和執行方式)
- 入口及返回值
- 實例:
function main(splash, args) splash:go("http://www.baidu.com") splash:wait(0.5) local title = splash:evaljs("document.title") return {title= title} end
將代碼貼到 http://localhost:8050/ 的代碼編輯區域,點擊 Render me!按鈕 測試
- 它返回網頁的標題,這里通過 evaljs()方法傳人 JavaScript 腳本,而 document.title 的執行結果就是返回網頁標題,執行完畢后將其賦值給一個 title 變量,隨后將其返回:
注意,在這里定義的方法名稱叫作 main()。這個名稱必須是固定的,Splash 會默認調用這個方法。
- 該方法的返回值既可以是字典形式,也可以是字符串形式,最后都會轉化為 Splash HTTP Response,例如:
function main(splash) return { hello="world" } end
返回一個字典形式的內容。如:
-
- 實例:
- 異步處理
- splash 支持異步處理,但這里並沒有顯式指明回調方法,其回調的跳轉是在 Splash 內部完成的。例:
function main(splash, args) local example_urls ={"www.baidu.com","www.taobao.com","www.zhihu.com"} 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 腳本中的字符串拼接和 Python 不同,它使用的是..操作符,而不是+。簡單了解 Lua 腳本的語法:http://www.runoob.com/lua/lua-basic-syntax.html。
- 這里做了加載時的異常檢測。go()方法會返回加載頁面的結果狀態,如果頁面州現 4xx 或 5xx 狀態碼,ok 變量就為空,不會返回加載后的圖片。
- splash 支持異步處理,但這里並沒有顯式指明回調方法,其回調的跳轉是在 Splash 內部完成的。例:
- Splash 對象屬性
- 前面例子中 main()方法的第一個參數是 splash,這個對象非常重要,類似於 Selenium 中的 WebDriver 對象,可以調用它的一些屬性和方法來控制加載過程。
- args
- args 屬性可以獲取加載時配置的參數,如 URL,如果為 GET 請求,還可以獲取 GET 請求參數;如果為 POST 請求,可以獲取表單提交的數據。Splash 也支持使用第二個參數直接作為 args,例:
function main(splash, args) local url = args.url end
這里第二個參數 args 就相當於 splash.args 屬性,以上代碼等價於:
function main(splash) local url = splash.url end
- args 屬性可以獲取加載時配置的參數,如 URL,如果為 GET 請求,還可以獲取 GET 請求參數;如果為 POST 請求,可以獲取表單提交的數據。Splash 也支持使用第二個參數直接作為 args,例:
- js_enabled
- js_enabled 屬性是 Splash 的 JavaScript 執行開關,可以將其配置為 true 或 false 來控制是否執行 JavaScript 代碼,默認為 true。如:這里禁止執行 JavaScript 代碼:
function main(splash, args) splash:go("https://www.baidu.com") splash.js_enabled = false local title = splash:evaljs("document.title") return{title= title} end
接着,重新調用 evaljs()方法執行 JavaScript 代碼,此時運行結果就會拋出異常:
{ "error": 400, "info": { "line_number": 1, "error": "')' expected near char(239)", "source": "[string \"function main(splash, args)\r...\"]", "message": "[string \"function main(splash, args)\r...\"]:1: ')' expected near char(239)", "type": "LUA_INIT_ERROR" }, "description": "Error happened while executing Lua script", "type": "ScriptError" }
一般來說,不用設置此屬性,默認開啟即可。
- js_enabled 屬性是 Splash 的 JavaScript 執行開關,可以將其配置為 true 或 false 來控制是否執行 JavaScript 代碼,默認為 true。如:這里禁止執行 JavaScript 代碼:
-
resource_timeout
-
此屬性可以設置加載的超時時間,單位是秒。如果設置為 0 或者 nil(類似 Python 中的 None ),代表不檢測超時。示例:
function main(splash) splash.resource_timeout = 0.1 assert(splash:go("https://www.taobao.com")) return splash:png() end
例,這里將超時時間設置為 0.1秒。如果在 0.1 秒之內沒有得到響應,就會拋出異常。 此屬性適合在網頁加載速度較慢的情況下設置,如果超過了某個時間無響應,則直接拋出異常並忽略即可。
-
-
images_enabled
-
images_enabled 屬性可以設置圖片是否加載,默認情況下是加載的。禁用該屬性后,可以節省網絡流量並提高網頁加載速度。注意:禁用圖片加載可能會影響 JavaScript 渲染。禁用圖片后,外層 DOM 節點的高度會受影響,進而影響 DOM 節點的位置。因此,如果 JavaScript 對圖片節點有操作的話,其執行就會受到影響。
-
注意:Splash 使用了緩存。如果一開始加載出來了網頁圖片,然后禁用了圖片加載, 再重新加載頁面,之前加載好的圖片可能還會顯示出來,這時直接重啟 Splash 即可。
-
禁用圖片加載的示例:
function main(splash, args) splash.images_enabled = false assert(splash:go('https://www.jd.com')) return { png=splash:png()} end
這樣返回的頁面截圖就不會帶有圖片,加載速度也會快很多
-
-
-
plugins_enabled
-
plugins_enabled 屬性可以控制瀏覽器插件(如 Flash 插件)是否開啟。默認情況下,此屬性是 false,表示不開啟。可以使用如下代碼控制其開啟和關閉:
splash。plugins_enabled = true/false
-
-
scroll_position
-
設置 scroll_position 屬性,可以控制頁面上下或左右滾動。是一個比較常用的屬性,示例如下:
function main(splash, args) assert(splash:go('https://www.taobao.com')) splash.scroll_position = {y=400} return {png=splash:png()} end
這樣我們就可以控制頁面向下滾動 400 像素值。
-
-
如果要讓頁面左右滾動,可以傳入 x 參數,代碼:
splash.scroll_position = {x=100,y=200}
-
-
Splash 對象的方法
-
除了前面介紹的屬性外,Splash 對象還有如下方法:
-
go()
-
go() 方法用來請求某個鏈接,而且它可以模擬 GET 和 POST 請求,同時支持傳入請求頭、表單等數據,用法:
ok, reason = spalsh:go{url, baseurl=nil,headers=nil,http_method="GET",body=nil,formdata=nil}
參數說明:
-
url:請求的URL\
-
baseurl:可選參數,默認為空,表示自願加載相對路徑。
-
headers:可選參數,默認為空,表示請求頭
-
http_method:可選參數,默認為空,發POST請求時的表單數據,使用Content-type 為application/json
-
formdata:可選參數,默認為空,POST的時候的表單數據,使用的Content-type為application/x-www-form-urlencoded、
-
-
該方法的返回結果是結果 ok 和原因 reason 的組合,如果 ok 為空,代表網頁加載出現了錯誤,此時 reason 變量中包含了錯誤的原因,否則證明頁面加載成功。示例:
function main(splash,args) local ok, reason = splash:go{"http://httpbin.org/post",http_method="POST",body="name=Germey"} if ok then return splash:html() end end
這里模擬了 POST 請求,並傳入了 POST 的表單數據,如果成功,則返回頁面的源代碼。運行結果:
<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{ "args": {}, "data": "", "files": {}, "form": { "name": "Germey" }, "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en,*", "Connection": "close", "Content-Length": "11", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "Origin": "null", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1" }, "json": null, "origin": "180.175.116.149", "url": "http://httpbin.org/post" } </pre></body></html>
成功實現POST請求並發送了表達數據。
-
-
wait()
-
wait() 方法可以控制頁面的等待時間,使用方法:
ok, reason = splash:wait{time,cancel_on_redirect=false,cancel_on_error=true}
參數說明
-
time:等待的秒數
-
cancel_on_redirect:可選參數,默認為false,表示如果發生了重定向就停止等待,並返回重定向結果
-
cancel_on_error:可選參數,默認為false,表示如果發生了加載錯誤,就停止等待。
-
-
返回結果同樣是結果 ok 和原因 reason 的組合。示例:
function main(splash) splash:go("https://www.taobao.com") splash:wait(2) return {html=splash:html()} end
該功能實訪問淘寶並等待2秒,隨后返回頁面源代碼的功能。
-
-
jsfunc()
-
jsfunc()方法可以直接調用 JavaScript 定義的方法,但所調用的方法需要用雙中括號包圍,相當於實現了 JavaScript 方法到 Lua 腳本的轉換。示例:
function main(splash,args) local get_div_count =splash:jsfunc([[ function(){ var body = document.body; var divs = body.getElementsByTagName('div'); return divs.length; } ]]) splash:go("https://www.baidu.com") return("There are %s DIVs"):format(get_div_count()) end 輸出: Splash Response: "There are 22 DIVs"
首先,聲明了一個 JavaScript 定義的方法,然后在頁面加載成功后調用此方法計算出頁面中 div 節點的個數。
-
關於 JavaScript 到 Lua 腳本的更多轉換細節,參考官方文檔: https://splash.readthedocs.io/en/ stable/scripting-ref.html#splash-jsfunc。
-
-
evaljs()
-
evaljs() 方法可以執行 JavaScript 代碼並返回最后一條 JavaScript 語句的返回結果,使用方法:
result = splash:evaljs(js)
如,可以用下面的代碼來獲取頁面標題:
local title = splash:evaljs("document.title")
-
-
runjs()
-
runjs() 方法可以執行 JavaScript 代碼,與 evaljs()的功能類似,但是更偏向於執行某些動作或聲明某些方法。例如:
function main(splash, args) splash:go("https://www.baidu.com") splash:runjs("foo = function(){return 'bar'}") local result = splash:evaljs("foo()") return result end 輸出: bar
用 runjs()先聲明一個 JavaScript 定義的方法,通過 evaljs()來調用得到的結果。
-
-
autoload()
-
autoload() 方法可以設置每個頁面訪問時自動加載的對象,使用方法:
ok, reason = splash:autoload{source_or_url, source=nil, url=nil}
參數說明:
-
source_or_url:JavaScript代碼或者JavaScript庫鏈接
-
source:JavaScript代碼
-
url:JavaScript庫鏈接
-
-
autoload() 方法只負責加載 JavaScript 代碼或庫,不執行任何操作。如果要執行操作,可以調用 evaljs() 或 runjs()方法。例:
function main(splash,args) splash:autoload([[ function get_document_title(){ return document.title; } ]]) splash:go("https://www.baidu.com") return splash:evaljs("get_document_title()") end
調用 autoload()方法聲明一個 JavaScript 方法,然后通過 evaljs ()方法來執行此 JavaScript 方法。輸出百度頁面文本。
-
另外,也可以使用 autoload()方法加載某些方法庫,如 jQuery,示例:
function main(splash, args) assert(splash:autoload("https://code.jquery.com/jquery-2.1.3.min.js")) assert(splash:go("https://www.taobao.com")) local version = splash:evaljs("$.fn.jquery") return 'JQuery version:'.. version end
輸出:"JQuery version:2.1.3"
-
-
call_later()
-
call_later() 方法可以通過設置定時任務和延遲時間來實現任務延時執行,井且可以在執行前通過 cancel () 方法重新執行定時任務。示例:
function main(splash,args) local snapshots = {} local timer = splash:call_later(function() snapshots["a"] = splash:png() splash:wait(1.0) snapshots["b"] = splash:png() end, 0.05) splash:go("https://www.taobao.com") splash:wait(3.0) return snapshots end
這里設置了一個定時任務,0.05 秒的時候獲取網頁截圖,然后等待 1 秒,1.05 秒時再次獲取網頁截圖,訪問的頁面是淘寶,最后將截圖結果返回。 結果將是:第一次截圖時網頁還沒有加載出來,第二次網頁加載成功。
-
-
http_get()
- http_get() 方法可以模擬發送 HTTP 的 GET 請求,使用方法:
response = splash:http_get{url,headers=nil,follow_redirects=true}
參數說明:
- url:請求URL
- headers:可選參數,默認是空,請求頭。
- follow_redirects:可選參數,表示十分期待自動重定向,默認為true。
- 示例:
function main(splash, args) local treat = require("treat") local response = splash:http_get("http://httpbin.org/get") return { html = treat.as_string(response.body), url=response.url, status=response.statsus } end
輸出結果:
Splash Response:Object html:String(length 355) { "args": {}, "headers": { "Accept-Encoding": "gzip, deflate", "Accept-Language": "en,*", "Connection": "close", "Host": "httpbin.org", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1" }, "origin": "180.175.116.149", "url": "http://httpbin.org/get" }
- http_get() 方法可以模擬發送 HTTP 的 GET 請求,使用方法:
- http_post()
- 與 http_get()方法類似,用來模擬發送 POST 請求,不過多了一個參數 body ,使用方法:
response = splash:http_post{url,headers=nil,follow_redirects=true, body=nil}
參數說明:
-
url:請求URL
- headers:可選參數,默認為空,請求頭
- follow_redirects:可選參數,表示是否啟動自動重定向,默認為true
- body:可選參數,即表單數據,默認為空。
-
- 示例:
function main(splash, args) local treat = require("treat") local json = require("json") local response = splash:http_post{"http://httpbin.org/post", body=json.encode({name ="Germey"}), headers={["content-type"]="application/json"} } return { html=treat.as_string(response.body), url=response.url, status=response.status } end
輸出:
Splash Response:Object html:String(length 535) { "args": {}, "data": "{\"name\": \"Germey\"}", "files": {}, "form": {}, "headers": { "Accept-Encoding": "gzip, deflate", "Accept-Language": "en,*", "Connection": "close", "Content-Length": "18", "Content-Type": "application/json", "Host": "httpbin.org", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1" }, "json": { "name": "Germey" }, "origin": "180.175.116.149", "url": "http://httpbin.org/post" }
這里成功模擬提交POST請求並發送表單數據。
- 與 http_get()方法類似,用來模擬發送 POST 請求,不過多了一個參數 body ,使用方法:
-
set_content()
-
set_content() 方法用來設置頁面內容,示例:
function main(splash) assert(splash:set_content("<html><body><h1>hello</h1></body></html>")) return splash:png() end
-
-
html()
- html() 方法用來獲取網頁的源代碼。示例:
function main(splash,args) splash:go("https://httpbin.org/get") return splash:html() end 輸出:
<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{ "args": {}, "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en,*", "Connection": "close", "Host": "httpbin.org", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1" }, "origin": "180.175.116.149", "url": "https://httpbin.org/get" } </pre></body></html>
- html() 方法用來獲取網頁的源代碼。示例:
-
png()
-
png() 方法用來獲取 PNG 格式的網頁截圖,示例:
function main(splash,args) splash:go("https://www.taobao.com") return splash:png() end
-
-
jpeg()
-
jpeg() 方法用來獲取 JPEG 格式的網頁截圖,示例:
function main(splash,args) splash:go("https://www.taobao.com") return splash:jpeg() end
-
-
har()
-
har() 方法用來獲取頁面加載過程描述,示例:
function main(splash, args) splash:go("https://www.baidu.com") return splash:har() end
輸出結果:
-
-
-
url()
-
url()方法可以獲取當前正在訪問的 URL,示例:
function main(splash,args) splash:go("https://www.baidu.com") return splash:url() end 輸出: "https://www.baidu.com/"
-
-
get_cookies()
- get_cookies() 方法可以獲取當前頁面的 Cookies,示例:
function main(splash, args) splash:go("https://www.baidu.com") return splash:get_cookies() end 輸出:
Splash Response: Array[7] 0: Object domain: ".baidu.com" expires: "2087-01-21T09:30:08Z" httpOnly: false name: "BAIDUID" path: "/" secure: false value: "70BACA9750D3C6FBE7DA3EDC2B9E0FCE:FG=1" 1: Object domain: ".baidu.com" expires: "2087-01-21T09:30:08Z" httpOnly: false name: "BIDUPSID" path: "/" secure: false value: "70BACA9750D3C6FBE7DA3EDC2B9E0FCE" 2: Object domain: ".baidu.com" expires: "2087-01-21T09:30:08Z" httpOnly: false name: "PSTM" path: "/" secure: false value: "1546496161" 3: Object domain: ".baidu.com" httpOnly: false name: "delPer" path: "/" secure: false value: "0" 4: Object domain: "www.baidu.com" httpOnly: false name: "BD_HOME" path: "/" secure: false value: "0" 5: Object domain: ".baidu.com" httpOnly: false name: "H_PS_PSSID" path: "/" secure: false value: "1456_21095_28206_28131_26350_28139_27543" 6: Object domain: "www.baidu.com" expires: "2019-01-13T06:16:01Z" httpOnly: false name: "BD_UPN" path: "/" secure: false value: "143354"
- get_cookies() 方法可以獲取當前頁面的 Cookies,示例:
- add_cookie()
- add_cookie() 方法可以為當前頁面添加 Cookie ,用法:
cookies = splash:add_cookie{name,value,path=nil,domain=nil,expires=nil,httpOnly=nil,secure=nil}
各個參數代表 Cookie 的各個屬性。示例:
function main(splash) splash:add_cookie{"sessionid","237465ghgfsd","/",domain="http://example.com"} splash:go("http://example.com/") return splash:html() end
- add_cookie() 方法可以為當前頁面添加 Cookie ,用法:
- clear_cookies()
- clear_cookies() 方法可以清除所有的 Cookies,示例:
function main(splash) splash:go("https://www.baidu.com") splash:clear_cookies() return splash:get_cookies() end
清除了所有的 Cookies,然后調用 get_cookies()將結果返回。 輸出:Splash Response: Array[0], Cookies 被全部清空。
- clear_cookies() 方法可以清除所有的 Cookies,示例:
-
get_viewport_size()
- get_viewport_size() 方法可以獲取當前瀏覽器頁面的大小,即寬高,示例:
function main(splash) splash:go("https://www.baidu.com/") return splash:get_viewport_size() end
輸出:
Splash Response: Array[2] 0: 1024 1: 768
- get_viewport_size() 方法可以獲取當前瀏覽器頁面的大小,即寬高,示例:
-
set_viewport_size()
-
set_viewport_size() 方法可以設置當前瀏覽器頁面的大小,即寬高,用法:
splash:set_viewport_size(width,height)
例:訪問一個寬度自適應的頁面:
function main(splash) splash:set_viewport_size(400,700) assert(splash:go("https://cuiqingcai.com")) return splash:png() end
-
-
set_viewport_full()
-
set_viewport_full() 方法可以設置瀏覽器全屏顯示,示例:
function main(splash) splash:set_viewport_full() assert(splash:go("https://www.cuiqingcai.com")) return splash:png() end
-
-
set_user_agent()
-
set_user_agent() 方法可以設置瀏覽器的 User-Agent,示例:
function main(splash) splash:set_user_agent('splash') splash:go("http://httpbin.org/get") return splash:html() end
這里將瀏覽器的 User-Agent 設置為 Splash. 結果:User-agent 被設置成功。
-
-
set_custom_headers()
-
set_custom_headers() 方法可以設置請求頭,示例:
function main(splash) splash:set_custom_headers({ ["User-Agent"] = "Splash", ["Site"] = "Splash", }) splash:go("http://httpbin.org/get") return splash:html() end
這里設置了請求頭中的 User-Agent 和 Site 屬性,輸出結果中User-Agent 和Site被更改。
-
-
select()
-
select()方法可以選中符合條件的第一個節點,如果有多個節點符合條件只會返回一個,其參數是 css 選擇器。示例:
function main(splash) splash:go("https://www.baidu.com") input = splash:select("#kw") input:send_text('Splash') splash:wait(3) return splash:png() end
首先訪問了百度,選中了搜索框,隨后調用 send_text()方法填寫了文本,然后返回網頁截圖。成功填寫了輸入框。
-
-
select_all()
-
select_all() 方法選中所有符合條件的節點,其參數是 CSS 選擇器。示例:
function main(splash) local treat = require('treat') assert(splash:go("http://quotes.toscrape.com/")) assert(splash:wait(0.5)) local texts = splash:select_all('.quote .text') local results = {} for index, text in ipairs(texts) do results[index] = text.node.innerHTML end return treat.as_array(results) end
這里通過 CSS 選擇器選中節點的正文內容,隨后遍歷了所有節點,將其中的文本獲取下來。
-
-
mouse_click()
-
mouse_click() 方法可以模擬鼠標點擊操作,傳入的參數為坐標值 X 和 Y。也可以直接選中某個節點,調用此方法,示例:
function main(splash) splash:go("https://www.baidu.com") input = splash:select("#kw") input:send_text('Splash') submit = splash:select('#su') submit:mouse_click() splash:wait(3) return splash:png() end
首先選中頁面的輸入框,輸入文本,然后選中“提交”按鈕,調用了 mouse_click() 方法提交查詢,然后頁面等待3秒,返回截圖。成功獲取了查詢后的頁面內容,模擬了百度搜索操作。
-
-
Splash 對象的所有 API 操作:詳細說明參見官方文檔 https://splash.readthedocs.io/en/stable/scripting-ref.html 。
-
針對頁面元素 API 操作:https://splash.readthedocs.io/en/stable/scripting-element-object.html。
-
- Splash API 調用
- Splash Lua 腳本是在 Splash 頁面中測試運行的,Splash 提供了一些 HTTPAPI 接口,只需請求這些接口並傳遞相應的參數即可。就可以利用 Splash 渲染頁面 和 Python 程序結合使用並抓取 JavaScript 渲染的頁面。
- render.html
- 接口用於獲取 JavaScript 渲染的頁面的 HTML 代碼,接口地址是 Splash 的運行地址加接口名稱,例: http://localhost:8050/render.html。用 curl 來測試一下:
curl http://localhost:8050/render.html?url=https://www.baidu.com
給此接口傳遞了一個 url 參數來指定渲染的 URL,返回結果即頁面渲染后的源代碼。用 Python 實現代碼:
import requests url = 'http://localhost:8050/render.html?url=https://www.baidu.com' response = requests.get(url) print(response.text)
這樣就可以成功輸出 百度頁面渲染后的源代碼了。
- 接口還可以指定其他參數,如通過 wait 指定等待秒數。如果要確保頁面完全加載出來,可以增加等待時間,例:
import requests url = 'http://localhost:8050/render.html?url=https://www.taobao.com&wait=5' response = requests.get(url) print(response.text)
此時得到響應的時間就會變長,如這里會等待 5 秒多鍾才能獲取淘寶頁面的源代碼。
- 接口還支持代理設置、圖片加載設置、Header 設置、請求方法設置,具體的用法見官方文檔:https://splash.readthedocs.io/en/stable/api.html#render-html。
- 接口用於獲取 JavaScript 渲染的頁面的 HTML 代碼,接口地址是 Splash 的運行地址加接口名稱,例: http://localhost:8050/render.html。用 curl 來測試一下:
- render.png
- 接口可以獲取網頁截圖,其參數比 render.html 多幾個,如通過 width 和 height 來控制寬高,返回的是 PNG 格式的圖片二進制數據。示例:
curl http://localhost:8050/render.png?url=https://www.taobao.com&wait=5&width=1000&height=700
這里傳入 width 和 height 來設置頁面大小為 1000 像素×700 像素。
- 如果用python實現,可以將返回的二進制數據保存為 PNG 格式的圖片,具體:
import requests url = 'http://localhost:8050/render.png?url=https://www.jd.com&wait=5&width=1000&height=700' response = requests.get(url) with open('taobao.png','wb') as f: f.write(response.content)
這樣就成功獲取了京東首頁渲染完成后的頁面截圖,詳細的參數設置參考官網文檔: https://splash.readthedocs.io/en/stable/api.html#render-png。
- 接口可以獲取網頁截圖,其參數比 render.html 多幾個,如通過 width 和 height 來控制寬高,返回的是 PNG 格式的圖片二進制數據。示例:
- render.jpeg
- render.jpej 接口和 render.png 類似,不過它返回的是 JPEG 格式的圖片二進制數據。
- 另外, 接口比 render.png 多了參數 quality,用來設置圖片質量。
- render.har()
- 接口用於獲取頁面加載的 HAR 數據,示例:
curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5
運回結果非常多,是一個 JSON 格式的數據,其中包含頁面加載過程中的 HAR 數據
- 接口用於獲取頁面加載的 HAR 數據,示例:
- render.json
- 接口包含前面接口的所有功能,返回結果是 JSON 格式,示例:
curl http://localhost:8050/render.json?url=https://httpbin.org
-
可以通過傳人不同參數控制其返回結果。如:傳人 html=1,返回結果即會增加源代碼數據;傳入 png=1 ,返回結果即會增加頁面 PNG 截圖數據;傳入 har=1 ,則會獲得頁面 HAR 數據。例:
curl http://localhost:8050/render.json?url=https://httpbin.org&html=1
這樣返回的 JSON 結果會包含網頁源代碼和 HAR 數據。
-
更多參數設置參考官方文檔: https://splash.readthedocs.io/en/stable/api.html#render-json。
- 接口包含前面接口的所有功能,返回結果是 JSON 格式,示例:
-
excute
-
excute() 接口是最為強大的接口。前面說了很多 Splash Lua 腳本的操作,用此接口便可實現與 Lua 本的對接。 前面的 render.html 和 render.png 等接口對於一般的 JavaScript 渲染頁面是足夠了,但是如果要實現一些交互操作的話,它們還是無能為力,這里就需要使用 execute 接口。 先實現一個最簡單的腳本,直接返回數據:
function main(splash) return 'hello' end
然后將腳本轉化為 URL 編碼后的字符串,拼接到 execute 接口后面,示例:
curl http://localhost:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend
通過 lua_source 參數傳遞了轉碼后的 Lua 腳本,通過 execute 接口獲取了最終腳本的執行結果。 用 Python 實現代碼:
import requests from urllib.parse import quote lua = ''' function main(splash) return 'hello' end ''' url = 'http://localhost:8050/execute?lua_source=' + quote(lua) response = requests.get(url) print(response.text) 輸出: hello
這里用 Python 中的三引號將 Lua 腳本包括起來,然后用 urllib.parse 模塊里的 quote()方法將腳本進行 URL 轉碼,隨后構造 Splash 請求 URL,將其作為 lua_source 參數傳遞,這樣運行結果就會顯示 Lua 腳本執行后的結果。
-
實例:
import requests from urllib.parse import quote lua = ''' function main(splash,args) local treat = require("treat") local response = splash:http_get("http://httpbin.org/get") return { html = treat.as_string(response.body), url=response.url, status=response.status } end ''' url = 'http://localhost:8050/execute?lua_source='+quote(lua) #不要忘記后面的‘=’ response = requests.get(url) print(response.text)
輸出:
{"html": "{\n \"args\": {}, \n \"headers\": {\n \"Accept-Encoding\": \"gzip, deflate\", \n \"Accept-Language\": \"en,*\", \n \"Connection\": \"close\", \n \"Host\": \"httpbin.org\", \n \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/9.0 Safari/602.1\"\n }, \n \"origin\": \"180.165.241.94\", \n \"url\": \"http://httpbin.org/get\"\n}\n", "status": 200, "url": "http://httpbin.org/get"}
返回結果是 JSON 形式,成功獲取了請求的 URL, 狀態碼和網頁源代碼。
-
之前所說 Lua 腳本均可以用此方式與 Python 進行對接,所有網頁的動態渲染,模擬點擊、表單提交、頁面滑動、延時等待后的一些結果均可以自由控制,獲取頁面源碼和截圖也都ok。
-