1. Splash介紹
Splash是一個JavaScript渲染服務,是一個帶有HTTP API的輕量級瀏覽器,同時它對接了Python中的Twisted和QT庫。利用它,我們同樣可以實現動態渲染頁面的抓取
2. 安裝
2.1 安裝docker(安裝方法看上一篇)
2.2 拉取鏡像
docker pull scrapinghub/splash
2.3 用docker運行scrapinghub/splash
docker run -p 8050:8050 scrapinghub/splash
2.4 查看效果
我們在8050端口上運行了Splash服務,打開http://192.168.99.100:8050/即可看到其Web頁面
3 Splash對象屬性
上圖中main()方法的第一個參數是splash,這個對象非常重要,它類似於Selenium中的WebDriver對象
3.1 images_enabled
設置圖片是否加載,默認情況下是加載的。禁用該屬性后,可以節省網絡流量並提高網頁加載速度
注意的是,禁用圖片加載可能會影響JavaScript渲染。因為禁用圖片之后,它的外層DOM節點的高度會受影響,進而影響DOM節點的位置
因此,如果JavaScript對圖片節點有操作的話,其執行就會受到影響
function main(splash, args) splash.images_enabled = false splash:go('https://www.baidu.com') return {html=splash:html()} end
3.2 plugins_enabled
可以控制瀏覽器插件(如Flash插件)是否開啟
默認情況下,此屬性是false,表示不開啟
splash.plugins_enabled = true/false
3.3 scroll_position
控制頁面上下或左右滾動
splash.scroll_position = {x=100, y=200}
4. Splash對象的方法
4.1 go()
該方法用來請求某個鏈接,而且它可以模擬GET和POST請求,同時支持傳入請求頭、表單等數據
ok, reason = splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil, formdata=nil}
返回結果是結果ok和原因reason
如果ok為空,代表網頁加載出現了錯誤,此時reason變量中包含了錯誤的原因
參數 | 含義 |
---|---|
url | 請求的URL |
baseurl | 可選參數,默認為空,表示資源加載相對路徑 |
headers | 可選參數,默認為空,表示請求頭 |
http_method | 可選參數,默認為GET,同時支持POST |
body | 可選參數,默認為空,發POST請求時的表單數據,使用的Content-type為application/json |
formdata | 可選參數,默認為空,POST的時候的表單數據,使用的Content-type為application/x-www-form-urlencoded |
splash:go{"http://www.sxt.cn", http_method="POST", body="name=17703181473"}
4.2 wait()
控制頁面的等待時間
splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}
參數 | 含義 |
---|---|
time | 等待的秒數 |
cancel_on_redirect | 可選參數,默認為false,表示如果發生了重定向就停止等待,並返回重定向結果 |
cancel_on_error | 可選參數,默認為false,表示如果發生了加載錯誤,就停止等待 |
function main(splash) splash:go("https://www.taobao.com") splash:wait(2) return {html=splash:html()} end
4.3 jsfunc()
直接調用JavaScript定義的方法,但是所調用的方法需要用雙中括號包圍,這相當於實現了JavaScript方法到Lua腳本的轉換
function main(splash, args) splash:go("http://www.sxt.cn") local scroll_to = splash:jsfunc("window.scrollTo") scroll_to(0, 300) return {png=splash:png()} end
4.4 evaljs()與 runjs()
- evaljs() 以執行JavaScript代碼並返回最后一條JavaScript語句的返回結果
- runjs() 以執行JavaScript代碼,它與evaljs()的功能類似,但是更偏向於執行某些動作或聲明某些方法
function main(splash, args) splash:go("https://www.baidu.com") splash:runjs("foo = function() { return 'sxt' }") local result = splash:evaljs("foo()") return result end
4.5 html()
獲取網頁的源代碼
function main(splash, args) splash:go("https://www.bjsxt.com") return splash:html() end
4.6 png()
獲取PNG格式的網頁截圖
function main(splash, args) splash:go("https://www.bjsxt.com") return splash:png() end
4.7 har()
獲取頁面加載過程描述
function main(splash, args) splash:go("https://www.bjsxt.com") return splash:har() end
4.8 url()
獲取當前正在訪問的URL
function main(splash, args) splash:go("https://www.bjsxt.com") return splash:url() end
4.9 get_cookies()
獲取當前頁面的Cookies
function main(splash, args) splash:go("https://www.bjsxt.com") return splash:get_cookies() end
4.10 add_cookie()
當前頁面添加Cookie
cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}
function main(splash) splash:add_cookie{"sessionid", "123456abcdef", "/", domain="http://bjsxt.com"} splash:go("http://bjsxt.com/") return splash:html() end
4.11 clear_cookies()
可以清除所有的Cookies
function main(splash) splash:go("https://www.bjsxt.com/") splash:clear_cookies() return splash:get_cookies() end
4.12 set_user_agent()
設置瀏覽器的User-Agent
function main(splash) splash:set_user_agent('Splash') splash:go("http://httpbin.org/get") return splash:html() end
4.13 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
4.14 select()
選中符合條件的第一個節點
如果有多個節點符合條件,則只會返回一個
其參數是CSS選擇器
function main(splash) splash:go("https://www.baidu.com/") input = splash:select("#kw") splash:wait(3) return splash:png() end
4.15 send_text()
填寫文本
function main(splash) splash:go("https://www.baidu.com/") input = splash:select("#kw") input:send_text('Splash') splash:wait(3) return splash:png() end
4.16 mouse_click()
模擬鼠標點擊操作
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
5 Splash與Python結合
5.1 render.html
此接口用於獲取JavaScript渲染的頁面的HTML代碼,接口地址就是Splash的運行地址加此接口名稱,例如
http://192.168.99.100:8050/render.html
import requests url = 'http://192.168.99.100:8050/render.html?url=https://www.bjsxt.com&wait=3' response = requests.get(url) print(response.text)
5.2 render.png
此接口可以獲取網頁截圖
import requests
url = 'http://192.168.99.100: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)
5.3 execute
最為強大的接口。前面說了很多Splash Lua腳本的操作,用此接口便可實現與Lua腳本的對接
import requests from urllib.parse import quote lua = ''' function main(splash) return 'hello' end ''' url = 'http://192.168.99.100:8050/execute?lua_source=' + quote(lua) response = requests.get(url) print(response.text)