记录在使用selenium过程中踩的坑------
在使用selenium时,用click点击网站弹出的文件上传框的“上传文件”按钮不生效,报错selenium.common.exceptions.InvalidArgumentException
log如下:
test_xxxxxx.py::test_xxxxxxx FAILED [100%]Traceback (most recent call last): File "F:\xxxxxxxx\page\BasePage.py", line 20, in box_click element.click() File "F:\Python\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click self._execute(Command.CLICK_ELEMENT) File "F:\Python\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute return self._parent.execute(command, params) File "F:\Python\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute self.error_handler.check_response(response) File "F:\Python\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.InvalidArgumentException: Message: invalid argument (Session info: chrome=78.0.3904.97)
元素的定位是这样: Select_File = (By.CSS_SELECTOR, "input[type=file]")
解决方法:
def action_click(self, locator):
temp = 1
log = self._log
while temp < 5:
try:
element = WebDriverWait(self._driver, 5, 1).until(expected_conditions.element_to_be_clickable(locator))
# element.click()
ActionChains(self._driver).click(element).perform()
except Exception as e:
time.sleep(0.5)
temp += 1
# traceback.print_exc()
log.logger.debug(traceback.print_exc())
else:
break
# 尝试5次仍失败,则终止
if temp == 5:
self.save_screen()
raise Exception("Fail to click")
把element.click()改为 ActionChains(self._driver).click(element).perform()

至于为什么第一种方式不可以,现在还没弄懂。
引申:
两种Click有什么不同?
下面是我的一点小见解。
我大致看了一下源码,第一种方式是对远程的web driver post 一个请求/session/$sessionId/element/$id/click 去进行click操作
Communicates with the Remote WebDriver server using the WebDriver wire protocol
https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol
Python\lib\site-packages\selenium\webdriver\remote\webelement.py
def click(self):
"""Clicks the element."""
self._execute(Command.CLICK_ELEMENT)
Python\Lib\site-packages\selenium\webdriver\remote\remote_connection.py
Command.CLICK_ELEMENT: ('POST', '/session/$sessionId/element/$id/click')
第二种方式是模拟鼠标操作,对元素进行点击,再post /session/$sessionId/actions
Python\Lib\site-packages\selenium\webdriver\common\action_chains.py
ActionChains are a way to automate low level interactions such as
mouse movements, mouse button actions, key press, and context menu interactions.
This is useful for doing more complex actions like hover over and drag and drop.
def click(self, on_element=None):
"""
Clicks an element.
:Args:
- on_element: The element to click.
If None, clicks on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
else:
self._actions.append(lambda: self._driver.execute(
Command.CLICK, {'button': 0}))
return self
Python\Lib\site-packages\selenium\webdriver\common\actions\action_builder.py
def perform(self):
enc = {"actions": []}
for device in self.devices:
encoded = device.encode()
if encoded['actions']:
enc["actions"].append(encoded)
self.driver.execute(Command.W3C_ACTIONS, enc)
Command.W3C_ACTIONS: ('POST', '/session/$sessionId/actions')