【问题标题】:What's the difference between `driver.execute_script("...")` and `driver.get("javascript: ..."` with geckodriver/Firefox?`driver.execute_script("...")` 和 `driver.get("javascript: ..."` 与 geckodriver/Firefox 有什么区别?
【发布时间】:2019-10-21 18:54:02
【问题描述】:

我认为,这个问题与 Selenium 的内部运作有关。在另一篇帖子Referer missing in HTTP header of Selenium request 中,很明显运行之间存在差异

driver.execute_script("window.location.href = '{}';".format(url))

driver.get("javascript: window.location.href = '{}'".format(url))

后一个命令会随请求一起发送Referer header,前一个不会。

此时如果这是所需的行为或错误,则无关紧要,两个命令都应该发送Referer。另外,window.location.href = ... 只是一个例子。

然而,很明显,使用命令 driver.execute_script("...")driver.get("javascript: ..." 运行 JavaScript 之间肯定存在差异,如果它们不会产生相同的结果。所以问题更多是关于两个命令在内部没有调用相同的 Selenium 代码这一事实。

这两个命令有什么区别?

【问题讨论】:

  • 您为什么要以复杂的方式调用url,如javascript: window.location.href = '{}'".format(url),而您拥有久经考验且强大的get("{}".format(url))?你的具体用例是什么?
  • 这可能是同一个调用,这意味着 .get 示例调用 (window.location.href = "") 两次。 Execute_script 也会先注入,然后调用。
  • 其他差异将涉及 .get 内部的任何验证/实用方法。 (它可能会稍微清理一下网址......不确定当里面有一个javascript调用时它会做什么......但它可能只是用URL替换整个东西,这样它就不会执行两次或得到进入某种循环。)
  • 我假设 Selenium 正在使用 window.location.href 进行页面更改。现在我查看了源代码,事实并非如此。 (打头...当然因为启动浏览器时的第一页是空白的并且无法插入JS!) .get (或navigationto)实际上发送了一个get 请求。所以不同之处在于,当您使用 .get 方法时,中间服务器(代理服务器?节点?)发送的是 get 请求,而不是浏览器。所以代理此时没有推荐人,但您的本地电话。

标签: python selenium webdriver geckodriver http-referer


【解决方案1】:

您的问题的答案取决于您的驱动程序运行的浏览器。 Selenium 本身不实现这些功能 - 它只是调用底层驱动程序的 API。

查看WebDriver.execute_scriptWebDriver.get 的来源——它们都只是调用self.execute,它执行对webdriver 的请求。

例如,Chrome 不支持带有 WebDriver.get 的 'javascript:' url,因为 2013,这可以在 chromium 的网络驱动程序 implementation 中看到。

直接运行 JS 脚本和导航到“javascript URL”之间的实际区别深深嵌入每个浏览器的实现中,并且可能不是很简单。您提到的差异的一个可能原因可能是实现细节-也许浏览器(在产生您提到的结果时使用)仅在高级导航命令的上下文中发送 Referer 标头(@ 987654330@),因此在普通的 javascript 触发导航中不包含一个。

【讨论】:

  • 根据您在那里写的内容,我的猜测似乎是错误的或不完整的。但是查看 geckodriver 代码,我没有看到任何提及 JS URL,这让我认为所有相关代码都在 firefox 引擎中,而不是 selenium 甚至 geckodriver。
  • 我的答案有什么要补充的吗?
【解决方案2】:

TL;DR:我对此感到好奇并开始回答。然后就出城了。

我不是想从@Ni 那里挖积分或任何东西。正如他所指出的,getexecute_script 调用 self.execute,而后者又调用了来自 Command 类的方法。例如,Command.GETCommand.EXECUTE_SCRIPT。这就是我觉得这条路很冷的地方......


源代码

https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/remote/webdriver.py

def get(self, url):
    """
    Loads a web page in the current browser session.
    """
    self.execute(Command.GET, {'url': url})

def execute_script(self, script, *args):
    """
    Synchronously Executes JavaScript in the current window/frame.

    :Args:
     - script: The JavaScript to execute.
     - \*args: Any applicable arguments for your JavaScript.

    :Usage:
        driver.execute_script('return document.title;')
    """
    converted_args = list(args)
    command = None
    if self.w3c:
        command = Command.W3C_EXECUTE_SCRIPT
    else:
        command = Command.EXECUTE_SCRIPT

    return self.execute(command, {
        'script': script,
        'args': converted_args})['value']

指向

https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/remote/command.py

class Command(object):
    """
    Defines constants for the standard WebDriver commands.
    While these constants have no meaning in and of themselves, they are
    used to marshal commands through a service that implements WebDriver's
    remote wire protocol:
        https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol
    """

https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/remote/remote_connection.py#L142 显示了一个名为self._commands 的私有方法,它是一个字典,其中包含与..remote/webdriver.py 中看到的语法相同的命令

例如:Command.GET: ('POST', '/session/$sessionId/url')self.execute(Command.GET, {'url': url})

self._commands 中的端点对应于https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#command-reference,所以这是“用于编组命令”的服务(?)或它的一部分......

(红宝石等效:https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/remote/commands.rb

【讨论】:

  • @finefoot:对不起,我没有。我很好奇命令是如何在引擎盖下发送的,所以我挖了一下。还在挖:)
猜你喜欢
  • 2021-02-16
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 2011-06-28
  • 2011-03-08
  • 2010-09-19
  • 2010-10-29
相关资源
最近更新 更多