一、Splash 的使用

Splash 是一个JavaScript 渲染服务,带有 HTTP API的轻量级浏览器,同时对接了 Python 中的 Twisted 和 QT 库。利用它,同样可以实现动态渲染页面的抓取。

  1. 实例引入
    • 通过 Splash 提供的 Web 页面来测试其渲染过程。例:在本机 8050 端口上运行 Splash 服务,打开 http://localhost:8050/ 即可看到其 Web 页面:Class 17 - 2 动态渲染页面爬取 — Splash
    • 黑色框显示的是一个渲染示例。上方有个输入框,默认是 http://google.com, 换成百度测试,将内容更改为 https://www.baidu.com,点击 Render me 按钮开始渲染。 结果:Class 17 - 2 动态渲染页面爬取 — Splash
    • 网页的返回结果呈现了渲染截图、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 脚本来控制了页面加载过程,加载过程完全模拟浏览器,最后可返回各种格式的结果,如:网页源码和截图等。
  2. 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 变量,随后将其返回:Class 17 - 2 动态渲染页面爬取 — Splash

        注意,在这里定义的方法名称叫作 main()。这个名称必须是固定的,Splash 会默认调用这个方法

      • 该方法的返回值既可以是字典形式,也可以是字符串形式,最后都会转化为 Splash HTTP Response,例如:
        function main(splash)
          return { hello="world"  }
        end

        返回一个字典形式的内容。如:

        • Class 17 - 2 动态渲染页面爬取 — Splash

    • 异步处理
      • 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

        输出:

      • Class 17 - 2 动态渲染页面爬取 — Splash

        • 在脚本内调用的 wait ()方法类似于 Python 中的 sleep(),其参数为等待的秒数。当 Splash 执行到此方法时,它会转而去处理其他任务,然后在指定的时间过后再回来继续处理。
        • 注意:Lua 脚本中的字符串拼接和 Python 不同,它使用的是..操作符,而不是+。简单了解 Lua 脚本的语法:http://www.runoob.com/lua/lua-basic-syntax.html。
        • 这里做了加载时的异常检测。go()方法会返回加载页面的结果状态,如果页面州现 4xx 或 5xx 状态码,ok 变量就为空,不会返回加载后的图片。
  3. 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
    • 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"
        }
        View Code

相关文章:

  • 2021-09-20
  • 2022-12-23
  • 2021-04-15
  • 2021-05-02
  • 2022-12-23
  • 2022-12-23
  • 2021-05-25
猜你喜欢
  • 2022-12-23
  • 2021-07-03
  • 2022-12-23
  • 2021-10-25
  • 2022-12-23
  • 2022-01-17
相关资源
相似解决方案