国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

旅行社應(yīng)做哪些網(wǎng)站網(wǎng)絡(luò)營銷成功案例分析其成功原因

旅行社應(yīng)做哪些網(wǎng)站,網(wǎng)絡(luò)營銷成功案例分析其成功原因,微信小網(wǎng)站是怎么做的,鮮花網(wǎng)站建設(shè)方案爬蟲專欄:http://t.csdnimg.cn/WfCSx Splash 的使用 Splash 是一個(gè) JavaScript 渲染服務(wù),是一個(gè)帶有 HTTP API 的輕量級(jí)瀏覽器,同時(shí)它對(duì)接了 Python 中的 Twisted 和 QT 庫。利用它,我們同樣可以實(shí)現(xiàn)動(dòng)態(tài)渲染頁面的抓取。 1. 功…

爬蟲專欄:http://t.csdnimg.cn/WfCSx

Splash 的使用

Splash 是一個(gè) JavaScript 渲染服務(wù),是一個(gè)帶有 HTTP API 的輕量級(jí)瀏覽器,同時(shí)它對(duì)接了 Python 中的 Twisted 和 QT 庫。利用它,我們同樣可以實(shí)現(xiàn)動(dòng)態(tài)渲染頁面的抓取。

1. 功能介紹

利用 Splash 我們可以實(shí)現(xiàn)如下功能:

  • 異步方式處理多個(gè)網(wǎng)頁渲染過程

  • 獲取渲染后的頁面的源代碼或截圖

  • 通過關(guān)閉圖片渲染或者使用 Adblock 規(guī)則來加快頁面渲染速度

  • 可執(zhí)行特定的 JavaScript 腳本

  • 可通過 Lua 腳本來控制頁面渲染過程

  • 獲取渲染的詳細(xì)過程并通過 HAR(HTTP Archive)格式呈現(xiàn)

接下來我們來了解一下它的具體用法。

2. 準(zhǔn)備工作

在開始之前,請(qǐng)確保已經(jīng)正確安裝好了 Splash 并可以正常運(yùn)行服務(wù)。如果沒有安裝,可以參考第 1 章。

3. 實(shí)例引入

首先,通過 Splash 提供的 Web 頁面來測(cè)試其渲染過程。例如,我們?cè)诒緳C(jī) 8050 端口上運(yùn)行了 Splash 服務(wù),打開 http://localhost:8050/ 即可看到其 Web 頁面。

在右側(cè)呈現(xiàn)的是一個(gè)渲染示例,我們可以看到在上方有一個(gè)輸入框,默認(rèn)是 http://google.com,我們?cè)谶@里換成百度測(cè)試一下,將內(nèi)容更改為:百度一下,你就知道,然后點(diǎn)擊按鈕,開始渲染,結(jié)果:

可以看到,網(wǎng)頁的返回結(jié)果呈現(xiàn)了渲染截圖、HAR 加載統(tǒng)計(jì)數(shù)據(jù)、網(wǎng)頁的源代碼。

通過 HAR 的結(jié)果可以看到,Splash 執(zhí)行了整個(gè)網(wǎng)頁的渲染過程,包括 CSS、JavaScript 的加載等過程,呈現(xiàn)的頁面和我們?cè)跒g覽器中得到的結(jié)果完全一致。

那么,這個(gè)過程由什么來控制呢?重新返回首頁,可以看到實(shí)際上是有一段腳本,內(nèi)容如下:

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

這個(gè)腳本實(shí)際上是用 Lua 語言寫的腳本。即使不懂這個(gè)語言的語法,但從腳本的表面意思,我們也可以大致了解到它首先調(diào)用 go 方法去加載頁面,然后調(diào)用 wait 方法等待了一定時(shí)間,最后返回了頁面的源碼、截圖和 HAR 信息。

到這里,我們大體了解了 Splash 是通過 Lua 腳本來控制了頁面的加載過程的,加載過程完全模擬瀏覽器,最后可返回各種格式的結(jié)果,如網(wǎng)頁源碼和截圖等。

接下來,我們就來了解 Lua 腳本的寫法以及相關(guān) API 的用法。

4. Splash Lua 腳本

Splash 可以通過 Lua 腳本執(zhí)行一系列渲染操作,這樣我們就可以用 Splash 來模擬類似 Chrome、PhantomJS 的操作了。

首先,我們來了解一下 Splash Lua 腳本的入口和執(zhí)行方式。

入口及返回值

首先,來看一個(gè)基本實(shí)例:

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/ 的代碼編輯區(qū)域,然后點(diǎn)擊 Render me! 按鈕來測(cè)試一下。

我們看到它返回了網(wǎng)頁的標(biāo)題,這里我們通過 evaljs 方法傳入 JavaScript 腳本,而 document.title 的執(zhí)行結(jié)果就是返回網(wǎng)頁標(biāo)題,執(zhí)行完畢后將其賦值給一個(gè) title 變量,隨后將其返回。

注意,我們?cè)谶@里定義的方法名稱叫作 main 。這個(gè)名稱必須是固定的,Splash 會(huì)默認(rèn)調(diào)用這個(gè)方法。

該方法的返回值既可以是字典形式,也可以是字符串形式,最后都會(huì)轉(zhuǎn)化為 Splash HTTP Response,例如:

function main(splash)return {hello="world!"}
end

這樣即返回了一個(gè)字典形式的內(nèi)容。

function main(splash)return 'hello'
end

這樣即返回了一個(gè)字符串形式的內(nèi)容,同樣是可以的。

異步處理

Splash 支持異步處理,但是這里并沒有顯式指明回調(diào)方法,其回調(diào)的跳轉(zhuǎn)是在 Splash 內(nèi)部完成的。示例如下:

function main(splash, args)local example_urls = {"www.baidu.com", "www.taobao.com", "www.zhihu.com"}local urls = args.urls or example_urlslocal results = {}for index, url in ipairs(urls) dolocal ok, reason = splash:go("http://" .. url)if ok thensplash:wait(2)results[url] = splash:png()endendreturn results
end

運(yùn)行后的返回結(jié)果是 3 個(gè)站點(diǎn)的截圖:

在腳本內(nèi)調(diào)用的 wait 方法類似于 Python 中的 sleep 方法,其參數(shù)為等待的秒數(shù)。當(dāng) Splash 執(zhí)行到此方法時(shí),它會(huì)轉(zhuǎn)而去處理其他任務(wù),然后在指定的時(shí)間過后再回來繼續(xù)處理。

這里值得注意的是,Lua 腳本中的字符串拼接和 Python 不同,它使用的是.. 操作符,而不是 +。如果有必要,可以簡單了解一下 Lua 腳本的語法,詳見 Lua 基本語法 | 菜鳥教程。

另外,這里做了加載時(shí)的異常檢測(cè)。go 方法會(huì)返回加載頁面的結(jié)果狀態(tài),如果頁面出現(xiàn) 4xx 或 5xx 狀態(tài)碼,ok 變量就為空,就不會(huì)返回加載后的圖片。

5. Splash 對(duì)象屬性

我們注意到,前面例子中 main 方法的第一個(gè)參數(shù)是 splash,這個(gè)對(duì)象非常重要,它類似于 Selenium 中的 WebDriver 對(duì)象,我們可以調(diào)用它的一些屬性和方法來控制加載過程。接下來,先看下它的屬性。

args

該屬性可以獲取加載時(shí)配置的參數(shù),比如 URL,如果為 GET 請(qǐng)求,它還可以獲取 GET 請(qǐng)求參數(shù);如果為 POST 請(qǐng)求,它可以獲取表單提交的數(shù)據(jù)。Splash 也支持使用第二個(gè)參數(shù)直接作為 args,例如:

function main(splash, args)local url = args.url
end

這里第二個(gè)參數(shù) args 就相當(dāng)于 splash.args 屬性,以上代碼等價(jià)于:

function main(splash)local url = splash.args.url
end
js_enabled

這個(gè)屬性是 Splash 的 JavaScript 執(zhí)行開關(guān),可以將其配置為 true 或 false 來控制是否執(zhí)行 JavaScript 代碼,默認(rèn)為 true。例如,這里禁止執(zhí)行 JavaScript 代碼:

function main(splash, args)splash:go("https://www.baidu.com")splash.js_enabled = falselocal title = splash:evaljs("document.title")return {title=title}
end

接著我們重新調(diào)用了 evaljs 方法執(zhí)行 JavaScript 代碼,此時(shí)運(yùn)行結(jié)果就會(huì)拋出異常:

{"error": 400,"type": "ScriptError","info": {"type": "JS_ERROR","js_error_message": null,"source": "[string \"function main(splash, args)\r...\"]","message": "[string \"function main(splash, args)\r...\"]:4: unknown JS error: None","line_number": 4,"error": "unknown JS error: None","splash_method": "evaljs"},"description": "Error happened while executing Lua script"
}

不過一般來說我們不用設(shè)置此屬性開關(guān),默認(rèn)開啟即可。

resource_timeout

此屬性可以設(shè)置加載的超時(shí)時(shí)間,單位是秒。如果設(shè)置為 0 或 nil(類似 Python 中的 None),代表不檢測(cè)超時(shí)。示例如下:

function main(splash)splash.resource_timeout = 0.1assert(splash:go('https://www.taobao.com'))return splash:png()
end

例如,這里將超時(shí)時(shí)間設(shè)置為 0.1 秒。如果在 0.1 秒之內(nèi)沒有得到響應(yīng),就會(huì)拋出異常,錯(cuò)誤如下:

{"error": 400,"type": "ScriptError","info": {"error": "network5","type": "LUA_ERROR","line_number": 3,"source": "[string \"function main(splash)\r...\"]","message": "Lua error: [string \"function main(splash)\r...\"]:3: network5"},"description": "Error happened while executing Lua script"
}

此屬性適合在網(wǎng)頁加載速度較慢的情況下設(shè)置。如果超過了某個(gè)時(shí)間無響應(yīng),則直接拋出異常并忽略即可。

images_enabled

此屬性可以設(shè)置圖片是否加載,默認(rèn)情況下是加載的。禁用該屬性后,可以節(jié)省網(wǎng)絡(luò)流量并提高網(wǎng)頁加載速度。但是需要注意的是,禁用圖片加載可能會(huì)影響 JavaScript 渲染。因?yàn)榻脠D片之后,它的外層 DOM 節(jié)點(diǎn)的高度會(huì)受影響,進(jìn)而影響 DOM 節(jié)點(diǎn)的位置。因此,如果 JavaScript 對(duì)圖片節(jié)點(diǎn)有操作的話,其執(zhí)行就會(huì)受到影響。

另外值得注意的是,Splash 使用了緩存。如果一開始加載出來了網(wǎng)頁圖片,然后禁用了圖片加載,再重新加載頁面,之前加載好的圖片可能還會(huì)顯示出來,這時(shí)直接重啟 Splash 即可。

禁用圖片加載的示例如下:

function main(splash, args)splash.images_enabled = falseassert(splash:go('https://www.jd.com'))return {png=splash:png()}
end

這樣返回的頁面截圖就不會(huì)帶有任何圖片,加載速度也會(huì)快很多。

plugins_enabled

此屬性可以控制瀏覽器插件(如 Flash 插件)是否開啟。默認(rèn)情況下,此屬性是 false,表示不開啟??梢允褂萌缦麓a控制其開啟和關(guān)閉:

splash.plugins_enabled = true/false
scroll_position

通過設(shè)置此屬性,我們可以控制頁面上下或左右滾動(dòng)。這是一個(gè)比較常用的屬性,示例如下:

function main(splash, args)assert(splash:go('https://www.taobao.com'))splash.scroll_position = {y=400}return {png=splash:png()}
end

這樣我們就可以控制頁面向下滾動(dòng) 400 像素值,結(jié)果如圖。

如果要讓頁面左右滾動(dòng),可以傳入 x 參數(shù),代碼如下:

splash.scroll_position = {x=100, y=200}

6. Splash 對(duì)象方法

除了前面介紹的屬性外,Splash 對(duì)象還有如下方法。

go

該方法用來請(qǐng)求某個(gè)鏈接,而且它可以模擬 GET 和 POST 請(qǐng)求,同時(shí)支持傳入請(qǐng)求頭、表單等數(shù)據(jù),其用法如下:

ok, reason = splash:go{url, baseurl=nil, headers=nil, http_method="GET", body=nil, formdata=nil}

參數(shù)說明如下:

  • url,即請(qǐng)求的 URL。

  • baseurl,可選參數(shù),默認(rèn)為空,資源加載相對(duì)路徑。

  • headers,可選參數(shù),默認(rèn)為空,請(qǐng)求的 Headers。

  • http_method,可選參數(shù),默認(rèn)為 GET,同時(shí)支持 POST。

  • body,可選參數(shù),默認(rèn)為空,POST 的時(shí)候的表單數(shù)據(jù),使用的 Content-type 為 application/json。

  • formdata,可選參數(shù),默認(rèn)為空,POST 的時(shí)候表單數(shù)據(jù),使用的 Content-type 為 application/x-www-form-urlencoded。

該方法的返回結(jié)果是結(jié)果 ok 和原因 reason 的組合,如果 ok 為空,代表網(wǎng)頁加載出現(xiàn)了錯(cuò)誤,此時(shí) reason 變量中包含了錯(cuò)誤的原因,否則證明頁面加載成功。示例如下:

function main(splash, args)local ok, reason = splash:go{"http://httpbin.org/post", http_method="POST", body="name=Germey"}if ok thenreturn splash:html()end
end

這里我們模擬了一個(gè) POST 請(qǐng)求,并傳入了 POST 的表單數(shù)據(jù),如果成功,則返回頁面的源代碼。

運(yùn)行結(jié)果如下:

<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":"60.207.237.85","url":"http://httpbin.org/post"
}
</pre></body></html>

可以看到,我們成功實(shí)現(xiàn)了 POST 請(qǐng)求并發(fā)送了表單數(shù)據(jù)。

wait

此方法可以控制頁面等待時(shí)間,使用方法如下:

ok, reason = splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}

參數(shù)說明如下:

  • time,等待的秒數(shù)。

  • cancel_on_redirect,可選參數(shù),默認(rèn) False,如果發(fā)生了重定向就停止等待,并返回重定向結(jié)果。

  • cancel_on_error,可選參數(shù),默認(rèn) False,如果發(fā)生了加載錯(cuò)誤就停止等待。

返回結(jié)果同樣是結(jié)果 ok 和原因 reason 的組合。

我們用一個(gè)實(shí)例感受一下:

function main(splash)splash:go("https://www.taobao.com")splash:wait(2)return {html=splash:html()}
end

如上代碼可以實(shí)現(xiàn)訪問淘寶并等待 2 秒,隨后返回頁面源代碼的功能。

jsfunc

此方法可以直接調(diào)用 JavaScript 定義的方法,但是所調(diào)用的方法需要用雙中括號(hào)包圍,這相當(dāng)于實(shí)現(xiàn)了 JavaScript 方法到 Lua 腳本的轉(zhuǎn)換。示例如下:

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

運(yùn)行結(jié)果:

There are 21 DIVs

首先,我們聲明了一個(gè) JavaScript 定義的方法,然后在頁面加載成功后調(diào)用了此方法計(jì)算出了頁面中 div 節(jié)點(diǎn)的個(gè)數(shù)。

關(guān)于 JavaScript 到 Lua 腳本的更多轉(zhuǎn)換細(xì)節(jié),可以參考官方文檔:Splash Scripts Reference — Splash 3.5 documentation。

evaljs

此方法可以執(zhí)行 JavaScript 代碼并返回最后一條 JavaScript 語句的返回結(jié)果,使用方法如下:

result = splash:evaljs(js)

比如,可以用下面的代碼來獲取頁面標(biāo)題:

local title = splash:evaljs("document.title")
runjs

此方法可以執(zhí)行 JavaScript 代碼,它與 evaljs 方法的功能類似,但是更偏向于執(zhí)行某些動(dòng)作或聲明某些方法。例如:

function main(splash, args)splash:go("https://www.baidu.com")splash:runjs("foo = function() {return 'bar'}")local result = splash:evaljs("foo()")return result
end

這里我們用 runjs 方法先聲明了一個(gè) JavaScript 定義的方法,然后通過 evaljs 方法來調(diào)用得到的結(jié)果。

運(yùn)行結(jié)果如下:

bar
autoload

此方法可以設(shè)置每個(gè)頁面訪問時(shí)自動(dòng)加載的對(duì)象,使用方法如下:

ok, reason = splash:autoload{source_or_url, source=nil, url=nil}

參數(shù)說明如下:

  • source_or_url,JavaScript 代碼或者 JavaScript 庫鏈接。

  • source,JavaScript 代碼。

  • url,JavaScript 庫鏈接

但是此方法只負(fù)責(zé)加載 JavaScript 代碼或庫,不執(zhí)行任何操作。如果要執(zhí)行操作,可以調(diào)用 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

這里我們調(diào)用 autoload 方法聲明了一個(gè) JavaScript 方法,然后通過 evaljs 方法來執(zhí)行此 JavaScript 方法。

運(yùn)行結(jié)果如下:

百度一下,你就知道

另外,我們也可以使用 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

運(yùn)行結(jié)果如下:

JQuery version: 2.1.3
call_later

此方法可以通過設(shè)置定時(shí)任務(wù)和延遲時(shí)間來實(shí)現(xiàn)任務(wù)延時(shí)執(zhí)行,并且可以在執(zhí)行前通過 cancel 方法重新執(zhí)行定時(shí)任務(wù)。示例如下:

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.2)splash:go("https://www.taobao.com")splash:wait(3.0)return snapshots
end

這里我們?cè)O(shè)置了一個(gè)定時(shí)任務(wù),0.2 秒的時(shí)候獲取網(wǎng)頁截圖,然后等待 1 秒,1.2 秒時(shí)再次獲取網(wǎng)頁截圖,訪問的頁面是淘寶,最后將截圖結(jié)果返回。運(yùn)行結(jié)果如圖。

可以發(fā)現(xiàn),第一次截圖時(shí)網(wǎng)頁還沒有加載出來,截圖為空,第二次網(wǎng)頁便加載成功了。

http_get

此方法可以模擬發(fā)送 HTTP 的 GET 請(qǐng)求,使用方法如下:

response = splash:http_get{url, headers=nil, follow_redirects=true}

參數(shù)說明如下:

  • url,請(qǐng)求 URL。

  • headers,可選參數(shù),默認(rèn)為空,請(qǐng)求的 Headers。

  • follow_redirects,可選參數(shù),默認(rèn)為 True,是否啟動(dòng)自動(dòng)重定向。

示例如下:

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

運(yùn)行結(jié)果如下:

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": "60.207.237.85", "url": "http://httpbin.org/get"
}
status: 200
url: "http://httpbin.org/get"
http_post

和 http_get 方法類似,此方法是模擬發(fā)送一個(gè) POST 請(qǐng)求,不過多了一個(gè)參數(shù) body,使用方法如下:

response = splash:http_post{url, headers=nil, follow_redirects=true, body=nil}

參數(shù)說明如下:

  • url,請(qǐng)求 URL。

  • headers,可選參數(shù),默認(rèn)為空,請(qǐng)求的 Headers。

  • follow_redirects,可選參數(shù),默認(rèn)為 True,是否啟動(dòng)自動(dòng)重定向。

  • body,可選參數(shù),默認(rèn)為空,即表單數(shù)據(jù)。

示例如下:

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

運(yùn)行結(jié)果:

Splash Response: Object
html: String (length 533)
{"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": "60.207.237.85", "url": "http://httpbin.org/post"
}
status: 200
url: "http://httpbin.org/post"

可以看到在這里我們成功模擬提交了 POST 請(qǐng)求并發(fā)送了表單數(shù)據(jù)。

set_content

此方法可以用來設(shè)置頁面的內(nèi)容,示例如下:

function main(splash)assert(splash:set_content("<html><body><h1>hello</h1></body></html>"))return splash:png()
end

運(yùn)行結(jié)果如圖所示:

html

此方法可以用來獲取網(wǎng)頁的源代碼,它是非常簡單又常用的方法,示例如下:

function main(splash, args)splash:go("https://httpbin.org/get")return splash:html()
end

運(yùn)行結(jié)果:

<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": "60.207.237.85", "url": "https://httpbin.org/get"
}
</pre></body></html>
png

此方法可以用來獲取 PNG 格式的網(wǎng)頁截圖,示例如下:

function main(splash, args)splash:go("https://www.taobao.com")return splash:png()
end
jpeg

此方法可以用來獲取 JPEG 格式的網(wǎng)頁截圖,示例如下:

function main(splash, args)splash:go("https://www.taobao.com")return splash:jpeg()
end
har

此方法可以用來獲取頁面加載過程描述,示例如下:

function main(splash, args)splash:go("https://www.baidu.com")return splash:har()
end

運(yùn)行結(jié)果如圖所示:

在這里顯示了頁面加載過程中的每個(gè)請(qǐng)求記錄詳情。

url

此方法可以獲取當(dāng)前正在訪問的 URL,示例如下:

function main(splash, args)splash:go("https://www.baidu.com")return splash:url()
end

運(yùn)行結(jié)果如下:

https://www.baidu.com/
get_cookies

此方法可以獲取當(dāng)前頁面的 Cookies,示例如下:

function main(splash, args)splash:go("https://www.baidu.com")return splash:get_cookies()
end

運(yùn)行結(jié)果如下:

Splash Response: Array[2]
0: Object
domain: ".baidu.com"
expires: "2085-08-21T20:13:23Z"
httpOnly: false
name: "BAIDUID"
path: "/"
secure: false
value: "C1263A470B02DEF45593B062451C9722:FG=1"
1: Object
domain: ".baidu.com"
expires: "2085-08-21T20:13:23Z"
httpOnly: false
name: "BIDUPSID"
path: "/"
secure: false
value: "C1263A470B02DEF45593B062451C9722"
add_cookie

此方法可以為當(dāng)前頁面添加 Cookies,用法如下:

cookies = splash:add_cookie{name, value, path=nil, domain=nil, expires=nil, httpOnly=nil, secure=nil}

方法的各個(gè)參數(shù)代表了 Cookie 的各個(gè)屬性。

示例如下:

function main(splash)splash:add_cookie{"sessionid", "237465ghgfsd", "/", domain="http://example.com"}splash:go("http://example.com/")return splash:html()
end
clear_cookies

此方法可以清除所有的 Cookies,示例如下:

function main(splash)splash:go("https://www.baidu.com/")splash:clear_cookies()return splash:get_cookies()
end

在這里我們清除了所有的 Cookies,然后再調(diào)用 get_cookies() 并將結(jié)果返回。

運(yùn)行結(jié)果:

Splash Response: Array[0]

可以看到 Cookies 被全部清空,沒有任何結(jié)果。

get_viewport_size

此方法可以獲取當(dāng)前瀏覽器頁面的大小,即寬高,示例如下:

function main(splash)splash:go("https://www.baidu.com/")return splash:get_viewport_size()
end

運(yùn)行結(jié)果:

Splash Response: Array[2]
0: 1024
1: 768
set_viewport_size

此方法可以設(shè)置當(dāng)前瀏覽器頁面的大小,即寬高,用法如下:

splash:set_viewport_size(width, height)

例如這里我們?cè)L問一個(gè)寬度自適應(yīng)的頁面,示例如下:

function main(splash)splash:set_viewport_size(400, 700)assert(splash:go("http://cuiqingcai.com"))return splash:png()
end

運(yùn)行結(jié)果如圖所示:

set_viewport_full

此方法可以設(shè)置瀏覽器全屏顯示,示例如下:

function main(splash)splash:set_viewport_full()assert(splash:go("http://cuiqingcai.com"))return splash:png()
end
set_user_agent

此方法可以設(shè)置瀏覽器的 User-Agent,示例如下:

function main(splash)splash:set_user_agent('Splash')splash:go("http://httpbin.org/get")return splash:html()
end

在這里我們將瀏覽器的 User-Agent 設(shè)置為 Splash,運(yùn)行結(jié)果如下:

<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": "Splash"}, "origin": "60.207.237.85", "url": "http://httpbin.org/get"
}
</pre></body></html>

可以看到此處 User-Agent 被成功設(shè)置。

set_custom_headers()

此方法可以設(shè)置請(qǐng)求的 Headers,示例如下:

function main(splash)splash:set_custom_headers({["User-Agent"] = "Splash",["Site"] = "Splash",})splash:go("http://httpbin.org/get")return splash:html()
end

在這里我們?cè)O(shè)置了 Headers 中的 User-Agent 和 Site 屬性,運(yùn)行結(jié)果:

<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", "Site": "Splash", "User-Agent": "Splash"}, "origin": "60.207.237.85", "url": "http://httpbin.org/get"
}
</pre></body></html>

可以看到結(jié)果的 Headers 中兩個(gè)字段被成功設(shè)置。

select

該方法可以選中符合條件的第一個(gè)節(jié)點(diǎn),如果有多個(gè)節(jié)點(diǎn)符合條件,則只會(huì)返回一個(gè),其參數(shù)是 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

這里我們首先訪問了百度,然后選中了搜索框,隨后調(diào)用了 send_text() 方法填寫了文本,然后返回網(wǎng)頁截圖。

結(jié)果如圖所示,可以看到,我們成功填寫了輸入框。

可以看到我們成功填寫了輸入框。

select_all()

此方法可以選中所有的符合條件的節(jié)點(diǎn),其參數(shù)是 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) doresults[index] = text.node.innerHTMLendreturn treat.as_array(results)
end

這里我們通過 CSS 選擇器選中了節(jié)點(diǎn)的正文內(nèi)容,隨后遍歷了所有節(jié)點(diǎn),將其中的文本獲取下來。

運(yùn)行結(jié)果如下:

Splash Response: Array[10]
0: "“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”"
1: "“It is our choices, Harry, that show what we truly are, far more than our abilities.”"
2: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
3: "“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”"
4: "“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”"
5: "“Try not to become a man of success. Rather become a man of value.”"
6: "“It is better to be hated for what you are than to be loved for what you are not.”"
7: "“I have not failed. I've just found 10,000 ways that won't work.”"
8: "“A woman is like a tea bag; you never know how strong it is until it's in hot water.”"
9: "“A day without sunshine is like, you know, night.”"

可以發(fā)現(xiàn)我們成功將 10 個(gè)節(jié)點(diǎn)的正文內(nèi)容獲取了下來。

mouse_click

此方法可以模擬鼠標(biāo)點(diǎn)擊操作,傳入的參數(shù)為坐標(biāo)值 x、y,也可以直接選中某個(gè)節(jié)點(diǎn)直接調(diào)用此方法,示例如下:

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

在這里我們首先選中了頁面的輸入框,輸入了文本,然后選中了提交按鈕,調(diào)用了 mouse_click() 方法提交查詢,然后頁面等待三秒,返回截圖,結(jié)果如圖所示:

可以看到在這里我們成功獲取了查詢后的頁面內(nèi)容,模擬了百度搜索操作。

以上我們介紹了 Splash 的常用 API 操作,還有一些 API 在這不再一一介紹,更加詳細(xì)和權(quán)威的說明可以參見官方文檔:Splash Scripts Reference — Splash 3.5 documentation,此頁面介紹了 splash 對(duì)象的所有 API 操作,另外還有針對(duì)于頁面元素的 API 操作,鏈接為:Element Object — Splash 3.5 documentation。

7. Splash API 調(diào)用

在上文中我們說明了 Splash Lua 腳本的用法,但這些腳本是在 Splash 頁面里面測(cè)試運(yùn)行的,我們?nèi)绾尾拍芾?Splash 來渲染頁面呢?怎樣才能和 Python 程序結(jié)合使用并抓取 JavaScript 渲染的頁面呢?

其實(shí) Splash 給我們提供了一些 HTTP API 接口,我們只需要請(qǐng)求這些接口并傳遞相應(yīng)的參數(shù)即可獲取頁面渲染后的結(jié)果,下面我們對(duì)這些接口進(jìn)行介紹:

render.html

此接口用于獲取 JavaScript 渲染的頁面的 HTML 代碼,接口地址就是 Splash 的運(yùn)行地址加此接口名稱,例如:http://localhost:8050/render.html,我們可以用 curl 來測(cè)試一下:

curl http://localhost:8050/render.html?url=https://www.baidu.com

我們給此接口傳遞了一個(gè) url 參數(shù)指定渲染的 URL,返回結(jié)果即頁面渲染后的源代碼。

如果用 Python 實(shí)現(xiàn)的話,代碼如下:

import requests
url = 'http://localhost:8050/render.html?url=https://www.baidu.com'
response = requests.get(url)
print(response.text)

這樣就可以成功輸出百度頁面渲染后的源代碼了。

另外,此接口還可以指定其他參數(shù),比如通過 wait 指定等待秒數(shù)。如果要確保頁面完全加載出來,可以增加等待時(shí)間,例如:

import requests  
url = 'http://localhost:8050/render.html?url=https://www.taobao.com&amp;wait=5'  
response = requests.get(url)  
print(response.text)

如果增加了此等待時(shí)間后,得到響應(yīng)的時(shí)間就會(huì)相應(yīng)變長,如在這里我們會(huì)等待大約 5 秒多鐘即可獲取 JavaScript 渲染后的淘寶頁面源代碼。

另外此接口還支持代理設(shè)置、圖片加載設(shè)置、Headers 設(shè)置、請(qǐng)求方法設(shè)置,具體的用法可以參見官方文檔:Splash HTTP API — Splash 3.5 documentation。

render.png

此接口可以獲取網(wǎng)頁截圖,其參數(shù)比 render.html 多了幾個(gè),比如通過 width 和 height 來控制寬高,它返回的是 PNG 格式的圖片二進(jìn)制數(shù)據(jù)。示例如下:

curl http://localhost:8050/render.png?url=https://www.taobao.com&wait=5&width=1000&height=700

在這里我們還傳入了 width 和 height 來放縮頁面大小為 1000x700 像素。

如果用 Python 實(shí)現(xiàn),我們可以將返回的二進(jìn)制數(shù)據(jù)保存為 PNG 格式的圖片,實(shí)現(xiàn)如下:

import requestsurl = '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)

得到的圖片如圖所示:

這樣我們就成功獲取了京東首頁渲染完成后的頁面截圖,詳細(xì)的參數(shù)設(shè)置可以參考官網(wǎng)文檔 Splash HTTP API — Splash 3.5 documentation。

render.jpeg

此接口和 render.png 類似,不過它返回的是 JPEG 格式的圖片二進(jìn)制數(shù)據(jù)。

另外此接口相比 render.png 還多了一個(gè)參數(shù) quality,可以用來設(shè)置圖片質(zhì)量。

render.har

此接口用于獲取頁面加載的 HAR 數(shù)據(jù),示例如下:

curl http://localhost:8050/render.har?url=https://www.jd.com&wait=5

返回結(jié)果非常多,是一個(gè) Json 格式的數(shù)據(jù),里面包含了頁面加載過程中的 HAR 數(shù)據(jù)。

結(jié)果如圖所示:

render.json

此接口包含了前面接口的所有功能,返回結(jié)果是 Json 格式,示例如下:

curl http://localhost:8050/render.json?url=https://httpbin.org

結(jié)果如下:

{"title": "httpbin(1): HTTP Client Testing Service", "url": "https://httpbin.org/", "requestedUrl": "https://httpbin.org/", "geometry": [0, 0, 1024, 768]}

可以看到,這里以 JSON 形式返回了相應(yīng)的請(qǐng)求數(shù)據(jù)。

我們可以通過傳入不同參數(shù)控制其返回結(jié)果。比如,傳入 html=1,返回結(jié)果即會(huì)增加源代碼數(shù)據(jù);傳入 png=1,返回結(jié)果即會(huì)增加頁面 PNG 截圖數(shù)據(jù);傳入 har=1,則會(huì)獲得頁面 HAR 數(shù)據(jù)。例如:

curl http://localhost:8050/render.json?url=https://httpbin.org&html=1&har=1

這樣返回的 Json 結(jié)果便會(huì)包含網(wǎng)頁源代碼和 HAR 數(shù)據(jù)。

還有更多參數(shù)設(shè)置可以參考官方文檔:Splash HTTP API — Splash 3.5 documentation。

execute

此接口才是最為強(qiáng)大的接口。前面說了很多 Splash Lua 腳本的操作,用此接口便可實(shí)現(xiàn)與 Lua 腳本的對(duì)接。

前面的 render.html 和 render.png 等接口對(duì)于一般的 JavaScript 渲染頁面是足夠了,但是如果要實(shí)現(xiàn)一些交互操作的話,它們還是無能為力,這里就需要使用 execute 接口了。

我們先實(shí)現(xiàn)一個(gè)最簡單的腳本,直接返回?cái)?shù)據(jù):

function main(splash)return 'hello'
end

然后將此腳本轉(zhuǎn)化為 URL 編碼后的字符串,拼接到 execute 接口后面,示例如下:

curl http://localhost:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend

運(yùn)行結(jié)果:

hello

這里我們通過 lua_source 參數(shù)傳遞了轉(zhuǎn)碼后的 Lua 腳本,通過 execute 接口獲取了最終腳本的執(zhí)行結(jié)果。

這里我們更加關(guān)心的肯定是如何用 Python 來實(shí)現(xiàn),上例用 Python 實(shí)現(xiàn)的話,代碼如下:

import requests
from urllib.parse import quotelua = '''
function main(splash)return 'hello'
end
'''url = 'http://localhost:8050/execute?lua_source=' + quote(lua)
response = requests.get(url)
print(response.text)

運(yùn)行結(jié)果:

hello

這里我們用 Python 中的三引號(hào)將 Lua 腳本包括起來,然后用 urllib.parse 模塊里的 quote() 方法將腳本進(jìn)行 URL 轉(zhuǎn)碼,隨后構(gòu)造了 Splash 請(qǐng)求 URL,將其作為 lua_source 參數(shù)傳遞,這樣運(yùn)行結(jié)果就會(huì)顯示 Lua 腳本執(zhí)行后的結(jié)果。

我們?cè)偻ㄟ^實(shí)例看一下:

import requests
from urllib.parse import quotelua = '''
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)

運(yùn)行結(jié)果:

{"url": "http://httpbin.org/get", "status": 200, "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\": \"60.207.237.85\", \n  \"url\": \"http://httpbin.org/get\"\n}\n"}

可以看到,返回結(jié)果是 JSON 形式,我們成功獲取了請(qǐng)求的 URL、狀態(tài)碼和網(wǎng)頁源代碼。

如此一來,我們之前所說的 Lua 腳本均可以用此方式與 Python 進(jìn)行對(duì)接,所有網(wǎng)頁的動(dòng)態(tài)渲染、模擬點(diǎn)擊、表單提交、頁面滑動(dòng)、延時(shí)等待后的一些結(jié)果均可以自由控制,獲取頁面源碼和截圖也都不在話下。

到現(xiàn)在為止,我們可以用 Python 和 Splash 實(shí)現(xiàn) JavaScript 渲染的頁面的抓取了。除了 Selenium,本節(jié)所說的 Splash 同樣可以做到非常強(qiáng)大的渲染功能,同時(shí)它也不需要瀏覽器即可渲染,使用非常方便。

http://aloenet.com.cn/news/41862.html

相關(guān)文章:

  • 循環(huán)視頻做網(wǎng)站背景百度知道問答
  • 深圳家居網(wǎng)站建設(shè)公司青島app開發(fā)公司
  • 免費(fèi)咨詢婦科醫(yī)生在線seo推廣百度百科
  • html個(gè)人網(wǎng)站完整代碼北京網(wǎng)站優(yōu)化指導(dǎo)
  • 如何搭建一個(gè)論壇網(wǎng)站企業(yè)網(wǎng)站設(shè)計(jì)圖片
  • 沭陽網(wǎng)站設(shè)計(jì)蘭州百度推廣的公司
  • 坪山建設(shè)網(wǎng)站網(wǎng)絡(luò)推廣員
  • wordpress 手動(dòng)安裝seo怎么做教程
  • 餐飲公司網(wǎng)站建設(shè)的特點(diǎn)免費(fèi)b站推廣網(wǎng)址有哪些
  • 網(wǎng)站底部代碼下載百度文庫首頁
  • python網(wǎng)站開發(fā)實(shí)踐免費(fèi)網(wǎng)站申請(qǐng)域名
  • 自己做的網(wǎng)站可以有多個(gè)前端嗎網(wǎng)站建設(shè)公司是怎么找客戶
  • 網(wǎng)站建設(shè) 上市公司杭州網(wǎng)站seo外包
  • 網(wǎng)站開發(fā)還找到工作嗎鏈網(wǎng)
  • 做網(wǎng)站建設(shè)要什么證小網(wǎng)站
  • 影樓網(wǎng)站推廣seo系統(tǒng)優(yōu)化
  • 網(wǎng)站建設(shè)方案模板高校引流軟件下載站
  • 做優(yōu)化網(wǎng)站是什么意思誰有推薦的網(wǎng)址
  • 有什么好看的網(wǎng)站seo系統(tǒng)培訓(xùn)
  • 如何侵入網(wǎng)站服務(wù)器免費(fèi)企業(yè)黃頁查詢官網(wǎng)
  • 宜興網(wǎng)站制作百度seo優(yōu)化及推廣
  • 政府網(wǎng)站建設(shè)運(yùn)行情況寧波seo免費(fèi)優(yōu)化軟件
  • 新網(wǎng)站優(yōu)化怎么做武漢seo優(yōu)化
  • 界面網(wǎng)站的風(fēng)格關(guān)鍵字c語言
  • 成都哪里有做網(wǎng)站建設(shè)的青島網(wǎng)站建設(shè)公司電話
  • 在小說網(wǎng)站做責(zé)編如何免費(fèi)發(fā)布廣告
  • 網(wǎng)站制作公司智能 樂云踐新做網(wǎng)站怎么優(yōu)化
  • 網(wǎng)站模板購買房地產(chǎn)估價(jià)師考試
  • 小程序開發(fā)平臺(tái)哪里做得好seo網(wǎng)站優(yōu)化培訓(xùn)怎么做
  • 可以免費(fèi)發(fā)帖的網(wǎng)站品牌廣告投放