第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

深入使用 Splash 服務(wù)

上一小節(jié)我們基于 Splash 服務(wù)以及 Scrapy-Splash 插件完成了今日頭條熱點數(shù)據(jù)的抓取,今天我們來詳細(xì)地介紹 Splash Lua 腳本中支持的相關(guān)方法與 Splash 對象屬性,并解決上一小節(jié)留下的作業(yè)題。

1. Splash Lua 腳本方法與相關(guān)屬性介紹

上一節(jié)我們簡單實用了 Splash 服務(wù),并基于默認(rèn)的腳本完成了頭條熱點新聞數(shù)據(jù)的爬取。我們現(xiàn)在來深入學(xué)習(xí) Splash 中 lua 腳本的使用。

1.1 Splash對象屬性

來看默認(rèn)的 Splash lua 腳本:

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

其中這個 splash 參數(shù)非常重要,從該參數(shù)中我們可以調(diào)用 Splash 對象的一些重要屬性和方法來控制加載的過程。我們來看看 Splash 對象最常用的幾種屬性:

  • args 屬性:如 splash.args.url 是獲取請求渲染的 url;

  • js_enabled 屬性:這個屬性可以用來允許或者禁止執(zhí)行 js 代碼。例如下面的 lua 腳本:

    function main(splash, args)
      splash.js_enabled = true
      assert(splash:go(args.url))
      assert(splash:wait(0.5))
      local title = splash:evaljs("document.title")
      return {
        title=title
      }
    end
    

    得到的結(jié)果為:

    Splash Response: Object
    title: "今日頭條"
    

    如果我們禁止執(zhí)行 js 代碼,即設(shè)置 splash.js_enabled = false,則渲染頁面時會報錯:
    圖片描述

禁止js后,執(zhí)行js語句報錯

resource_timeout 屬性:該屬性用于設(shè)置頁面加載時間,單位為秒。如果設(shè)置為0或者 nil (相當(dāng)于 Python 中的 None),表示不檢測超時;

images_enabled 屬性:用于設(shè)置是否加載圖片,默認(rèn)為 true,表示加載頁面圖片,設(shè)置為 false 后,表示禁止加載圖片,這有可能會改變頁面的布局,使用時要注意。另外,注意 Splash 使用了緩存,如果頭一次設(shè)置 true 并加載頁面,之后再設(shè)置為 false 后加載頁面仍然會有圖片顯示,這正是緩存的影響。只需要重啟 splash 服務(wù)即可顯示正常;
圖片描述

圖片描述

小米網(wǎng)站,禁止加載圖片

plugins_enabled 屬性:該屬性用于控制瀏覽器插件是否開啟,默認(rèn)情況下為 false;

scroll_position 屬性:該屬性用于控制頁面上下或者左右滾動。它是一個字典類型,key 為 x 表示頁面水平滾動位置,key 為 y 表示頁面垂直滾動的位置;我們繼續(xù)拿頭條的熱點新聞做實驗。之前默認(rèn)訪問時的頁面如下:

圖片描述

默認(rèn)訪問頭條熱點新聞

從抓取的網(wǎng)頁上看,一共獲取了12篇熱點新聞。接下來我們使用 scroll_position 屬性來將頁面滾動滾動,測試的 lua code 如下:

function main(splash, args)
  assert(splash:go(args.url))
  assert(splash:wait(2))
  splash.scroll_position = {y=1000}
  assert(splash:wait(2))
  splash.scroll_position = {y=1500}
  assert(splash:wait(5))
  return {
    png=splash:png(),
    html=splash:html()
  }
end

這里我做了2次頁面滾動,渲染的效果如下:
圖片描述

滾動后的效果

可以看到,頁面確實出現(xiàn)了滾動,且我們獲取的新聞數(shù)據(jù)已經(jīng)變多了,從渲染的頁面上看,我們已經(jīng)抓到了36條數(shù)據(jù)。

1.2 Splash 的常用方法

前面從默認(rèn)的 lua 腳本中我們已經(jīng)看到了 Splash 的一些常用方法,如 go()、wait()、html()、png() 等,我們來一一進(jìn)行介紹:

splash:go():這個方法比較熟悉了,就是跳轉(zhuǎn)去對應(yīng)的 url 地址,目前它只支持 GET 和 POST 請求。該方法支持指定 HTTP 請求頭,表單等數(shù)據(jù)。對應(yīng)的方法原型如下:

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

函數(shù)參數(shù)以及返回結(jié)果詳情可參考:splash:go,官方已經(jīng)給出了非常詳細(xì)的說明,這里就不再進(jìn)行翻譯了。

splash:wait(): 控制頁面等待時間,函數(shù)原型如下:

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

cancel_on_redirect 參數(shù)默認(rèn)為 false,表示如果等待中發(fā)生重定向則停止等待并返回重定向結(jié)果;cancel_on_error 默認(rèn)為 true,表示在等待渲染中出現(xiàn)了錯誤則停止等待并返回 nil, "<error string>",其中 error string 指的是加載錯誤的原因;

三個和執(zhí)行 js 相關(guān)的方法:

splash:jsfunc(),該方法用于將 JavaScript 方法轉(zhuǎn)換成 Lua 中可調(diào)用的方法。注意所調(diào)用的 JavaScript 函數(shù)必須在一對雙中括號內(nèi),類似如下寫法:

function main(splash, args)
  -- get_div_count 就是表示jsfunc中定義的js方法
  local get_div_count = splash:jsfunc([[
  function () {
    var body = document.body;
    var divs = body.getElementsByTagName('div');
    return divs.length;
  }
  ]])
  splash:go(args.url)

  return ("There are %s DIVs in %s"):format(
    get_div_count(), args.url)
end

splash:evaljs(),直接在渲染的頁面中執(zhí)行 js 腳本。來看看如下示例:

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

splash:runjs(),它和 evaljs() 方法功能類似,也是執(zhí)行 JavaScript 代碼。前者它更偏向于執(zhí)行某些動作或者定義某些方法:

-- 這樣子的寫法,foo便會加入到全局上下文中,下面注釋的這樣寫法就是錯誤的
-- assert(splash:runjs("function foo(){return 'bar'}"))
-- 下面這個為正確寫法
assert(splash:runjs("foo = function (){return 'bar'}"))
local res = splash:evaljs("foo()")  -- this returns 'bar'

splash:autoload(),該方法用于設(shè)置每個頁面訪問時自動加載的 JavaScript 代碼,該方法只負(fù)責(zé)加載代碼并不執(zhí)行。我們通常會用該方法去加載一些必須的 js 庫函數(shù),如 jQuery 等,也會使用該方法加載我們自定義的 js 函數(shù)。

assert(splash:autoload("https://code.jquery.com/jquery-2.1.3.min.js"))

splash:call_later(),該方法通過設(shè)置任務(wù)的延長時間來實現(xiàn)任務(wù)的延遲執(zhí)行。

splash:http_get(),該方法發(fā)送 http 的 get 請求并返回響應(yīng),方法的原型如下:

response = splash:http_get{url, headers=nil, follow_redirects=true}
  • splash:http_post(),該方法發(fā)送 http 的 post 請求并返回響應(yīng),方法的原型如下:

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

splash:set_content(),該方法用于設(shè)置當(dāng)前頁面的內(nèi)容并等待頁面加載;我們來看看官方給的一個簡單示例:

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

渲染效果如下:

圖片描述

  • splash:html():獲取渲染后的網(wǎng)頁源碼;

  • splash:png():獲取 png 格式的頁面截圖;

  • splash:jpg():獲取 jpg 格式的頁面截圖;

  • splash:url():獲取當(dāng)前訪問頁面的 url;

cookie 相關(guān)的方法:

  • splash:get_cookies():獲取 CookieJar 的內(nèi)容-腳本中所有 cookies 的列表;

  • splash:add_cookie():添加一個 cookie;

  • splash:init_cookies():將當(dāng)前所有 cookies 替換成傳入的 cookies

  • splash:clean_cookies():清除所有的 cookies;

  • splash:delete_cookies():刪除指定的 cookies;

  • splash:set_viewport_full():設(shè)置瀏覽器全屏顯示;

  • splash:on_request():在每個 http 請求之前注冊要調(diào)用的函數(shù)。這個方法非常有用,官方給出了6中用途示例,如記錄所有的請求、丟棄某個特殊的請求 (比如以 .css 結(jié)尾的請求) 等,這也從某方面說明了該方法的重要性;

接下來我們看看 Splash 中一些更高級的用法,包括頁面元素定位、填充輸入框以及模擬鼠標(biāo)操作等方法。

2. Splash 中元素定位與操作

Splash 中涉及到元素定位和操作的方法主要有如下幾個:

  • splash:select():從當(dāng)前網(wǎng)頁的 DOM 中選擇與指定 CSS 選擇器匹配的第一個 HTML 元素;
  • splash:select_all():從當(dāng)前網(wǎng)頁的 DOM 中選擇與指定 CSS 選擇器匹配的 HTML 元素列表;
  • splash:send_keys():將鍵盤事件發(fā)送到頁面上下文;
  • splash:send_text():將文本作為輸入發(fā)送到頁面上下文,一個字符一個字符發(fā)送;

來看看我們對這些方法的一個簡單實例:

function main(splash)
   splash:go("https://www.baidu.com")
   splash:wait(2)
   input = splash:select("#kw")
   input:send_text("慕課網(wǎng) wiki")
   splash:wait(2)
   return  {
      png = splash:png()
  }
end

來看看針對百度頁面的執(zhí)行效果:
圖片描述

使用 splash 服務(wù)獲取百度搜索結(jié)果

另外一個例子,我們還是前面的頭條熱點數(shù)據(jù),我們加上滾動效果后能提取出更多的熱點新聞,那么就在這里使用 splash:select_all() 方法將這些熱點新聞的標(biāo)題提取出來。為此,我們編寫如下的 lua 代碼:

function main(splash, args)
  local treat = require('treat')
  assert(splash:go(args.url))
  assert(splash:wait(2))
  splash.scroll_position = {y=1000}
  assert(splash:wait(2))
  splash.scroll_position = {y=1500}
  assert(splash:wait(5))
  news_list = splash:select_all('div.title-box a')
  local result = {}
  for idx, a in ipairs(news_list) do
     result[idx] = a.node.innerHTML
  end
  return treat.as_array(result)
end

來看看渲染后的結(jié)果,如下:
圖片描述

使用 select_all() 方法提取熱點新聞標(biāo)題

3. 模擬鼠標(biāo)操作

最后一部分我們來看看和鼠標(biāo)操作相關(guān)的方法,總共有4個方法:

  • splash:mouse_click():模擬鼠標(biāo)的點擊動作,該方法的原型為 splash:mouse_click(x, y);

    示例1

    local button = splash:select('button')
    -- 對于選中的button元素執(zhí)行點擊動作
    button:mouse_click()
    

    示例2

    -- 通過(x, y)坐標(biāo)執(zhí)行鼠標(biāo)點擊動作
    function main(splash)
        assert(splash:go(splash.args.url))
        -- 定義js函數(shù)
        local get_dimensions = splash:jsfunc([[
            function () {
                var rect = document.getElementById('button').getClientRects()[0];
                return {"x": rect.left, "y": rect.top}
            }
        ]])
        splash:set_viewport_full()
        splash:wait(0.1)
        -- 執(zhí)行js方法,獲取元素的坐標(biāo)位置
        local dimensions = get_dimensions()
        -- FIXME: button must be inside a viewport
        splash:mouse_click(dimensions.x, dimensions.y)
    
        -- Wait split second to allow event to propagate.
        splash:wait(0.1)
        return splash:html()
    end
    
  • splash:mouse_hover():模擬鼠標(biāo)懸停事件,方法原型為 splash:mouse_hover(x, y);

  • splash:mouse_press():在網(wǎng)頁中觸發(fā)鼠標(biāo)按下事件,方法原型為 splash:mouse_press(x, y);

  • splash:mouse_release():在網(wǎng)頁中觸發(fā)鼠標(biāo)釋放事件。方法原型為 splash:mouse_release(x, y);

4. 小結(jié)

本小節(jié)中我們深入學(xué)習(xí)了 Splash 服務(wù)的使用,并詳細(xì)介紹了 Splash 的部分屬性以及相關(guān)方法,部分屬性和方法給予詳細(xì)的實戰(zhàn)例子。接下來的兩節(jié)我們會介紹一種自動化測試工具,和 Splash 服務(wù)功能類似,但是更為強大和簡單易用,還等什么,快來學(xué)習(xí)吧!