如何使用 Selenium Safari 和 Python 通过输入标签上传文件

How to upload a file through the input tag using Selenium Safari and Python

我有一个适用于 chrome 和 firefox 的 selenium 脚本。我需要添加对 safari (13) 的支持。这是通过 LambdaTest 工作的硒网格。

我遇到了 Safari 文件上传问题。这是适用于其他浏览器的代码:

file_input = self.driver1.find_elements_by_css_selector("input[type='file']")[0]
time.sleep(2)
file_input.send_keys(DIR_PATH + r"/snap1.jpg")
time.sleep(2

使用 safari 我收到此错误消息:

selenium.common.exceptions.InvalidArgumentException: Message: One or more files could not be selected.

此错误源于 send_keys() 行。 DIR_PATH 定义为 os.path.dirname(os.path.realpath(__file__))snap1.jpg 是一个 jpg 文件,与我的 selenium 测试位于同一目录中。

我无法找到有关此特定错误的任何信息。有什么建议吗?

此错误消息...

selenium.common.exceptions.InvalidArgumentException: Message: One or more files could not be selected.

...表示 SafariDriver 无法将字符序列发送到 <input> 字段。


深入探讨

@jmleyba在他的comment中明确提到:

The SafariDriver is implemented in JS and does not have the privileges necessary to manipulate a element. Therefore, the SafariDriver does not support file uploads.

@jmleyba 进一步在另一个 comment 添加:

you cannot set the value of an <input type="file"> element (the path of the file that should be uploaded by the browser). The behavior is currently undefined. The SafariDriver will probably generate a series of key events on the element with no discernable effect. We should probably generate an error when the target is a file element.

但是 @mangaroo 建议解决方法如下:

I guess workaround for those that really want to do file upload for SafariDriver would be not to do it natively via SafariDriver but by using external code libraries to perform the upload via HTTP/HTTPS (POST) requests (combining any other form data in addition to the file being uploaded/sent), then get response and check whether upload succeeded or not, then go back to SafariDriver code and navigate to next page to check upload succeeded or not, and/or to continue from there for the next steps in the automation.

This approach would be similar to the file download method using HTTP requests externally that has been mentioned in various posts in WebDriver and Selenium user Google groups. Here, it's just the inverse, doing upload instead of download.

Though if the upload requires a session (cookie), then you can extract Selenium session cookie and use with HTTP request. Or if session is stored with session ID in URL, extract that and pass along with HTTP request.


结论

SafariDriver 不支持通过 <input type="file"> 上传文件。另一种方法是使用 HTTP/HTTPS 方法(通常通过 HTTP/HTTPS POST 请求将文件作为 POST 正文发送)通过 Safari 上传文件。

最新版本的 SafariDriver 可以使用 sendKeys 上传文件。

检查您的文件输入并确保它接受的文件类型与您尝试上传的文件类型没有区别。

例如

<input type="file" accept="image/jpeg" >

即使您要上传 .png 文件,这也适用于 ChromeDriver 或 GeckoDriver(但不适用于 SafariDriver)。