はじめに
PythonのSeleniumでファイルのアップロードを行う場合、type="file"
なinput要素に対してsend_keys(/path/to/file)
によりファイルを選択できます1。一見input要素がないように見えてもCSSで非表示になっている場合がほとんどのため、多くの場合はこの方法で対応できます(CSSを変更してwebdriverがinput要素にアクセスできるようにする必要はあります。)
しかし、ファイル選択にinput要素を用いないページもあり、ドラッグ&ドロップでのファイル選択が必要になる場合があります。そのような場合には下記の方法が有効です。
方法
florentbr/#wd-drop-file.py - GitHub Gist のコードを利用します。
from selenium import webdriver
from selenium.webdriver.remote.webelement import WebElement
import os.path
with open("wd-drop-file.min.js", "r") as f:
JS_DROP_FILES = f.read()
def drop_files(element, files, offsetX=0, offsetY=0):
driver = element.parent
isLocal = not driver._is_remote or '127.0.0.1' in driver.command_executor._url
paths = []
# ensure files are present, and upload to the remote server if session is remote
for file in (files if isinstance(files, list) else [files]) :
if not os.path.isfile(file) :
raise FileNotFoundError(file)
paths.append(file if isLocal else element._upload(file))
value = '\n'.join(paths)
elm_input = driver.execute_script(JS_DROP_FILES, element, offsetX, offsetY)
elm_input._execute('sendKeysToElement', {'value': [value], 'text': value})
WebElement.drop_files = drop_files
# 以下、利用例
driver = webdriver.Chrome()
driver.get("https://react-dropzone.js.org/")
dropzone = driver.find_element_by_css_selector("[data-preview='Basic example'] [style]")
dropzone.drop_files("C:\\temp\\image1.png")
Gistを見ていただければ全部わかりますが、コードはこのようになります。wd-drop-file.min.js
はGistを参照してください。オリジナルはJS_DROP_FILES
を直に入力していますが、このコードでは外部ファイルから読み込むようにしています。