記錄在使用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')