使用Splash中的Lua脚本访问google.com的DOM

问题描述

我正在尝试在Splash中运行Lua脚本以执行Google搜索获取搜索结果的屏幕截图。当我尝试在Lua脚本中使用xpath或CSS选择器选择Google搜索框时,出现此错误

{
    "error": 400,"type": "ScriptError","description": "Error happened while executing Lua script","info": {
        "message": "[string \"function main(splash,args)\r...\"]:9: cannot select the specified element {'type': 'JS_ERROR','js_error_type': 'SyntaxError','js_error_message': 'SyntaxError: DOM Exception 12','js_error': 'Error: SyntaxError: DOM Exception 12','message': \"JS error: 'Error: SyntaxError: DOM Exception 12'\"}","type": "SPLASH_LUA_ERROR","splash_method": "select","source": "[string \"function main(splash,args)\r...\"]","line_number": 9,"error": "cannot select the specified element {'type': 'JS_ERROR','message': \"JS error: 'Error: SyntaxError: DOM Exception 12'\"}"
    }
}

这是我的Lua脚本:

function main(splash,args)

  splash.private_mode_enabled = false
  splash:set_user_agent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0")
  
  assert(splash:go(args.url))
  assert(splash:wait(1.0))

  search_Box = assert(splash:select("//div[@class='a4bIc']/input"))
  search_Box:focus()
  search_Box:send_text('my user agent')
  search_Box:send_keys('<Enter>')
  assert(splash:wait(2.0))
  
  return splash:png()
end

我尝试设置自定义标头,以私有模式运行脚本,但是没有任何效果。 但是,使用duckduckgo.com时,同一脚本运行时不会出现错误,并且输出正确。当目标网址为google.com时会出现问题。 我认为Google检测到浏览器是由bot(脚本)控制的,因此它禁用了对DOM树的访问。

有任何想法如何使其起作用吗?

解决方法

选择器出问题了。

"//div[@class='a4bIc']/input"

打开网页,点击F12,然后使用检查器找出该输入字段要定位的div类。他们的类名也可能是在运行时生成的,以便对其进行混淆。

,

页面可能尚未完全下载/呈现

function main(splash,args)
    splash.private_mode_enabled = false
    splash:set_user_agent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0")

    local ok,reason = assert( splash:go(args.url) )

    if ok then
        local wait,increment,maxwait = 0,0.1,10
        while wait < maxwait and not splash:select("//div[@class='a4bIc']/input") do
            splash:wait(increment)  --  wait until it exists,or times out
            wait = wait +increment
        end
        if wait >= maxwait then
            print('Timed out')
        else
            search_box = splash:select("//div[@class='a4bIc']/input")
            search_box:focus()
            search_box:send_text('my user agent')
            search_box:send_keys('<Enter>')
            splash:wait(2.0)
            return splash:png()
        end
    else
        print( reason )  --  see if it tells you why
    end
end