`driver.execute_script("...")` 和 `driver.get("javascript: ..."` 与 geckodriver/Firefox 有什么区别?
What's the difference between `driver.execute_script("...")` and `driver.get("javascript: ..."` with geckodriver/Firefox?
我认为,这个问题涉及Selenium 的内部工作原理。在另一个 post 中,很明显 运行
之间存在差异
driver.execute_script("window.location.href = '{}';".format(url))
和
driver.get("javascript: window.location.href = '{}'".format(url))
后面的命令会在请求中发送Referer
头,前者不会。
在这一点上,这是期望的行为还是错误并不重要,Referer
应该由两个命令发送。另外,window.location.href = ...
只是一个例子。
然而,显然,运行 JavaScript 与命令 driver.execute_script("...")
和 driver.get("javascript: ..."
之间肯定存在差异,如果它们不产生相同的结果。所以问题更多的是关于这两个命令不会在内部调用相同的 Selenium 代码这一事实。
这两个命令有什么区别?
TL;DR:我对此很好奇并开始回答。然后出城了。
我不是想从@Ni 那里挖点数或任何东西。正如他指出的那样,get
和 execute_script
调用 self.execute
,后者又调用 Command
class 中的方法。例如,Command.GET
或 Command.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,所以这是服务"used to marshal commands"(?)或其一部分...
(ruby 等价于: https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/remote/commands.rb)
您问题的答案取决于浏览器,您的 driver 是 运行。 Selenium 本身不实现这些功能 - 它仅调用底层 driver 的 API.
查看 WebDriver.execute_script
and WebDriver.get
的来源 - 他们都只是调用 self.execute
,它执行对网络的请求driver。
例如,Chrome 不支持带有 WebDriver.get
的 'javascript:' url,因为 2013, as can bee seen in chromium's webdriver implementation.
直接 运行 JS 脚本和导航到 'javascript URL' 之间的实际区别深植于每个浏览器的实现中,并且可能不是很简单。您提到的差异的一个可能原因可能是实现细节 - 也许浏览器(在生成您提到的结果时使用)仅在 Referer
header 的上下文中发送高级导航命令 (driver.get
),因此没有包含在普通 javascript-triggered 导航中。
我认为,这个问题涉及Selenium 的内部工作原理。在另一个 post 中,很明显 运行
之间存在差异driver.execute_script("window.location.href = '{}';".format(url))
和
driver.get("javascript: window.location.href = '{}'".format(url))
后面的命令会在请求中发送Referer
头,前者不会。
在这一点上,这是期望的行为还是错误并不重要,Referer
应该由两个命令发送。另外,window.location.href = ...
只是一个例子。
然而,显然,运行 JavaScript 与命令 driver.execute_script("...")
和 driver.get("javascript: ..."
之间肯定存在差异,如果它们不产生相同的结果。所以问题更多的是关于这两个命令不会在内部调用相同的 Selenium 代码这一事实。
这两个命令有什么区别?
TL;DR:我对此很好奇并开始回答。然后出城了。
我不是想从@Ni 那里挖点数或任何东西。正如他指出的那样,get
和 execute_script
调用 self.execute
,后者又调用 Command
class 中的方法。例如,Command.GET
或 Command.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,所以这是服务"used to marshal commands"(?)或其一部分...
(ruby 等价于: https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/remote/commands.rb)
您问题的答案取决于浏览器,您的 driver 是 运行。 Selenium 本身不实现这些功能 - 它仅调用底层 driver 的 API.
查看 WebDriver.execute_script
and WebDriver.get
的来源 - 他们都只是调用 self.execute
,它执行对网络的请求driver。
Chrome 不支持带有 WebDriver.get
的 'javascript:' url,因为 2013, as can bee seen in chromium's webdriver implementation.
直接 运行 JS 脚本和导航到 'javascript URL' 之间的实际区别深植于每个浏览器的实现中,并且可能不是很简单。您提到的差异的一个可能原因可能是实现细节 - 也许浏览器(在生成您提到的结果时使用)仅在 Referer
header 的上下文中发送高级导航命令 (driver.get
),因此没有包含在普通 javascript-triggered 导航中。