Ale*_*lex 10 selenium selenium-webdriver
我正在使用远程seleniumwebdriver执行一些测试.但是,在某些时候,我需要下载一个文件并检查其内容.
我使用远程webdriver如下(in python):
PROXY = ...
prefs = {
"profile.default_content_settings.popups":0,
"download.prompt_for_download": "false",
"download.default_directory": os.getcwd(),
}
chrome_options = Options()
chrome_options.add_argument("--disable-extensions")
chrome_options.add_experimental_option("prefs", prefs)
webdriver.DesiredCapabilities.CHROME['proxy'] = {
"httpProxy":PROXY,
"ftpProxy":PROXY,
"sslProxy":PROXY,
"noProxy":None,
"proxyType":"MANUAL",
"class":"org.openqa.selenium.Proxy",
"autodetect":False
}
driver = webdriver.Remote(
command_executor='http://aaa.bbb.ccc:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME)
Run Code Online (Sandbox Code Playgroud)
使用"普通"webdriver,我可以在本地计算机上下载文件而不会出现问题.然后我可以使用测试代码来验证下载文件的内容(可以根据测试参数进行更改).它不是对下载本身的测试,但我需要一种方法来验证生成的文件的内容 ......
但是如何使用远程 webdriver 做到这一点?我在任何地方都找不到任何帮助......
Selenium API不提供在远程计算机上下载文件的方法.
但单凭Selenium仍然可以取决于浏览器.
使用Chrome,可以通过导航来chrome://downloads/检索下载的文件,并使用<input type="file">页面中执行的请求进行检索:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import os, time, base64
def get_downloaded_files(driver):
if not driver.current_url.startswith("chrome://downloads"):
driver.get("chrome://downloads/")
return driver.execute_script( \
"return downloads.Manager.get().items_ "
" .filter(e => e.state === 'COMPLETE') "
" .map(e => e.filePath || e.file_path); " )
def get_file_content(driver, path):
elem = driver.execute_script( \
"var input = window.document.createElement('INPUT'); "
"input.setAttribute('type', 'file'); "
"input.hidden = true; "
"input.onchange = function (e) { e.stopPropagation() }; "
"return window.document.documentElement.appendChild(input); " )
elem._execute('sendKeysToElement', {'value': [ path ], 'text': path})
result = driver.execute_async_script( \
"var input = arguments[0], callback = arguments[1]; "
"var reader = new FileReader(); "
"reader.onload = function (ev) { callback(reader.result) }; "
"reader.onerror = function (ex) { callback(ex.message) }; "
"reader.readAsDataURL(input.files[0]); "
"input.remove(); "
, elem)
if not result.startswith('data:') :
raise Exception("Failed to get file content: %s" % result)
return base64.b64decode(result[result.find('base64,') + 7:])
capabilities_chrome = { \
'browserName': 'chrome',
# 'proxy': { \
# 'proxyType': 'manual',
# 'sslProxy': '50.59.162.78:8088',
# 'httpProxy': '50.59.162.78:8088'
# },
'goog:chromeOptions': { \
'args': [
],
'prefs': { \
# 'download.default_directory': "",
# 'download.directory_upgrade': True,
'download.prompt_for_download': False,
'plugins.always_open_pdf_externally': True,
'safebrowsing_for_trusted_sources_enabled': False
}
}
}
driver = webdriver.Chrome(desired_capabilities=capabilities_chrome)
#driver = webdriver.Remote('http://127.0.0.1:5555/wd/hub', capabilities_chrome)
# download a pdf file
driver.get("https://www.mozilla.org/en-US/foundation/documents")
driver.find_element_by_css_selector("[href$='.pdf']").click()
# list all the completed remote files (waits for at least one)
files = WebDriverWait(driver, 20, 1).until(get_downloaded_files)
# get the content of the first file remotely
content = get_file_content(driver, files[0])
# save the content in a local file in the working directory
with open(os.path.basename(files[0]), 'wb') as f:
f.write(content)
Run Code Online (Sandbox Code Playgroud)
使用Firefox,一旦上下文切换到chrome://downloads/以下内容,可以通过使用脚本调用浏览器API直接列出和检索文件:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import os, time, base64
def get_file_names_moz(driver):
driver.command_executor._commands["SET_CONTEXT"] = ("POST", "/session/$sessionId/moz/context")
driver.execute("SET_CONTEXT", {"context": "chrome"})
return driver.execute_async_script("""
var { Downloads } = Components.utils.import('resource://gre/modules/Downloads.jsm', {});
Downloads.getList(Downloads.ALL)
.then(list => list.getAll())
.then(entries => entries.filter(e => e.succeeded).map(e => e.target.path))
.then(arguments[0]);
""")
driver.execute("SET_CONTEXT", {"context": "content"})
def get_file_content_moz(driver, path):
driver.execute("SET_CONTEXT", {"context": "chrome"})
result = driver.execute_async_script("""
var { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
OS.File.read(arguments[0]).then(function(data) {
var base64 = Cc["@mozilla.org/scriptablebase64encoder;1"].getService(Ci.nsIScriptableBase64Encoder);
var stream = Cc['@mozilla.org/io/arraybuffer-input-stream;1'].createInstance(Ci.nsIArrayBufferInputStream);
stream.setData(data.buffer, 0, data.length);
return base64.encodeToString(stream, data.length);
}).then(arguments[1]);
""", path)
driver.execute("SET_CONTEXT", {"context": "content"})
return base64.b64decode(result)
capabilities_moz = { \
'browserName': 'firefox',
'marionette': True,
'acceptInsecureCerts': True,
'moz:firefoxOptions': { \
'args': [],
'prefs': {
# 'network.proxy.type': 1,
# 'network.proxy.http': '12.157.129.35', 'network.proxy.http_port': 8080,
# 'network.proxy.ssl': '12.157.129.35', 'network.proxy.ssl_port': 8080,
'browser.download.dir': '',
'browser.helperApps.neverAsk.saveToDisk': 'application/octet-stream,application/pdf',
'browser.download.useDownloadDir': True,
'browser.download.manager.showWhenStarting': False,
'browser.download.animateNotifications': False,
'browser.safebrowsing.downloads.enabled': False,
'browser.download.folderList': 2,
'pdfjs.disabled': True
}
}
}
# launch Firefox
# driver = webdriver.Firefox(capabilities=capabilities_moz)
driver = webdriver.Remote('http://127.0.0.1:5555/wd/hub', capabilities_moz)
# download a pdf file
driver.get("https://www.mozilla.org/en-US/foundation/documents")
driver.find_element_by_css_selector("[href$='.pdf']").click()
# list all the downloaded files (waits for at least one)
files = WebDriverWait(driver, 20, 1).until(get_file_names_moz)
# get the content of the last downloaded file
content = get_file_content_moz(driver, files[0])
# save the content in a local file in the working directory
with open(os.path.basename(files[0]), 'wb') as f:
f.write(content)
Run Code Online (Sandbox Code Playgroud)
如果您使用 webdriver,则意味着您的代码使用内部 Selenium 客户端和服务器代码与浏览器实例进行通信。下载的文件存储在本地机器中,可以使用java、python、.Net、node.js等语言直接访问。
\n如果您使用Remote webdriver意味着您正在使用GRID概念,Gird的主要目的是To distribute your tests over multiple machines or virtual machines (VMs)。在此,您的代码使用 Selenium 客户端与 Selenium Grid Server 进行通信,Selenium Grid Server 将指令传递到使用指定浏览器的注册节点。他们的网格节点会将指令从特定于浏览器的驱动程序传递到浏览器实例。此处下载发生在file-system | hard-disk该系统的文件系统上,但用户无权访问运行浏览器的虚拟机上的文件系统。
\n\n\n
\n- \n
通过使用javascript,如果我们可以访问该文件,那么我们可以将文件转换为base64-String并返回给客户端代码。但出于安全原因,Javascript 不允许从磁盘读取文件。
\n- \n
如果 Selenium Grid 集线器和节点位于同一系统中,并且它们位于公共网络中,那么您可以将下载文件的路径更改为某些公共下载路径,例如
\n../Tomcat/webapps/Root/CutrentTimeFolder/file.pdf. 通过使用公共 URL,您可以直接访问该文件。
例如从tomcat的根文件夹下载文件[]。
\nSystem.out.println("FireFox Driver Path \xc2\xab "+ geckodriverCloudRootPath);\nFile temp = File.createTempFile("geckodriver", null);\ntemp.setExecutable(true);\nFileUtils.copyURLToFile(new URL( geckodriverCloudRootPath ), temp);\n\nSystem.setProperty("webdriver.gecko.driver", temp.getAbsolutePath() );\ncapabilities.setCapability("marionette", true);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n
\n- 如果 Selenium Grid Hub 和 Node 不在同一系统中,您可能无法获取下载的文件,因为 Grid Hub 将在公共网络中
\n[WAN],而 Node 将在[LAN]组织的专用网络中。
您可以将浏览器的下载文件路径更改为硬盘上的指定文件夹。通过使用下面的代码。
\nString downloadFilepath = "E:\\\\download";\n \nHashMap<String, Object> chromePrefs = new HashMap<String, Object>();\nchromePrefs.put("profile.default_content_settings.popups", 0);\nchromePrefs.put("download.default_directory", downloadFilepath);\nChromeOptions options = new ChromeOptions();\nHashMap<String, Object> chromeOptionsMap = new HashMap<String, Object>();\noptions.setExperimentalOption("prefs", chromePrefs);\noptions.addArguments("--test-type");\noptions.addArguments("--disable-extensions"); //to disable browser extension popup\n\nDesiredCapabilities cap = DesiredCapabilities.chrome();\ncap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap);\ncap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);\ncap.setCapability(ChromeOptions.CAPABILITY, options);\nRemoteWebDriver driver = new ChromeDriver(cap);\nRun Code Online (Sandbox Code Playgroud)\n@ 看
\n\n小智 6
@FlorentB 对 Chrome 的回答适用于 Chrome 版本 79。对于较新的版本,该功能get_downloaded_files需要更新,因为downloads.Manager不再可以访问。但是,此更新版本也应该适用于以前的版本。
def get_downloaded_files(driver):
if not driver.current_url.startswith("chrome://downloads"):
driver.get("chrome://downloads/")
return driver.execute_script( \
"return document.querySelector('downloads-manager') "
" .shadowRoot.querySelector('#downloadsList') "
" .items.filter(e => e.state === 'COMPLETE') "
" .map(e => e.filePath || e.file_path || e.fileUrl || e.file_url); ")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9229 次 |
| 最近记录: |