Selenium 4 文件上传和下载操作指南

Selenium 文件上传和下载 | 菜鸟教程这篇文章讲了Selenium4 文件上传和下载的基本知识点,我建议你先看完上面那篇文章学习基础,然后再学习下面的。

一、文件上传

1. 基本文件上传(使用 send_keys)

对于标准的 <input type="file"> 元素,最简单的方法是直接使用 send_keys() 发送文件路径:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://example.com/upload")

# 找到文件上传输入框
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")

# 发送文件绝对路径
file_input.send_keys("/path/to/your/file.txt")

# 点击上传按钮(如果有)
upload_button = driver.find_element(By.ID, "upload-button")
upload_button.click()

2. 处理隐藏的文件输入框

有些网站使用自定义样式隐藏了原生的文件输入框,然后通过 JavaScript 触发文件选择。对于这种情况:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com/upload")

# 找到隐藏的文件输入框(可能需要查看页面源代码)
hidden_file_input = driver.find_element(By.ID, "hidden-file-input")

# 使用JavaScript使元素可见(如果需要)
driver.execute_script("arguments[0].style.display = 'block';", hidden_file_input)

# 发送文件路径
hidden_file_input.send_keys("/path/to/your/file.txt")

3. 使用 AutoIT 或 Sikuli 处理系统对话框(不推荐)

对于某些无法直接通过 Selenium 操作的系统级文件选择对话框,可以考虑使用 AutoIT 或 Sikuli,但这些方法不够稳定且跨平台性差,应尽量避免。

4. 多文件上传

如果需要上传多个文件,可以发送多个文件路径,用换行符分隔:

python 复制代码
# 上传多个文件
file_input.send_keys("/path/to/file1.txt\n/path/to/file2.txt\n/path/to/file3.txt")

二、文件下载

1. 配置浏览器下载选项

在 Selenium 4 中,我们可以通过浏览器选项来配置下载行为:

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# 设置下载选项
chrome_options = Options()

# 设置下载路径
download_dir = "/path/to/download/directory"

# Chrome 浏览器配置
prefs = {
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,  # 禁止弹出下载对话框
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True  # 禁用安全浏览,以避免下载延迟
}

chrome_options.add_experimental_option("prefs", prefs)

# 创建浏览器实例
driver = webdriver.Chrome(options=chrome_options)

2. 等待下载完成

下载文件后,我们需要等待下载完成:

python 复制代码
import os
import time

def wait_for_download_complete(download_dir, timeout=30, check_interval=1):
    """
    等待下载目录中的 .crdownload 文件消失(Chrome)
    """
    end_time = time.time() + timeout
    while time.time() < end_time:
        # 检查是否有未完成的下载文件(Chrome使用.crdownload扩展名)
        if not any(fname.endswith('.crdownload') for fname in os.listdir(download_dir)):
            return True
        time.sleep(check_interval)
    return False

# 点击下载链接
download_link = driver.find_element(By.ID, "download-link")
download_link.click()

# 等待下载完成
if wait_for_download_complete(download_dir):
    print("下载完成")
else:
    print("下载超时")

3. 获取下载的文件信息

python 复制代码
def get_downloaded_file_info(download_dir, pattern=None):
    """
    获取下载目录中的文件信息
    """
    files = []
    for filename in os.listdir(download_dir):
        filepath = os.path.join(download_dir, filename)
        if os.path.isfile(filepath):
            # 如果指定了模式,只返回匹配的文件
            if pattern and not pattern in filename:
                continue
            files.append({
                "name": filename,
                "path": filepath,
                "size": os.path.getsize(filepath),
                "modified": os.path.getmtime(filepath)
            })
    
    # 按修改时间排序,最新的在前
    files.sort(key=lambda x: x["modified"], reverse=True)
    return files

# 获取所有下载的文件
downloaded_files = get_downloaded_file_info(download_dir)

# 获取最新下载的文件
if downloaded_files:
    latest_file = downloaded_files[0]
    print(f"最新下载的文件: {latest_file['name']}, 大小: {latest_file['size']} 字节")

4. 处理不同浏览器的下载

不同浏览器需要不同的配置:

Chrome 浏览器
python 复制代码
chrome_options = Options()
prefs = {
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True
}
chrome_options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=chrome_options)
Firefox 浏览器
python 复制代码
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service

firefox_options = Options()
firefox_options.set_preference("browser.download.folderList", 2)  # 0=桌面, 1=默认, 2=自定义
firefox_options.set_preference("browser.download.dir", download_dir)
firefox_options.set_preference("browser.download.useDownloadDir", True)
firefox_options.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream,application/pdf,text/csv")
firefox_options.set_preference("pdfjs.disabled", True)  # 禁用内置PDF查看器

driver = webdriver.Firefox(options=firefox_options)
Edge 浏览器
python 复制代码
from selenium.webdriver.edge.options import Options

edge_options = Options()
prefs = {
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True
}
edge_options.add_experimental_option("prefs", prefs)
driver = webdriver.Edge(options=edge_options)

三、实战示例:完整的文件上传和下载流程

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import os
import time

# 设置下载目录
download_dir = os.path.abspath("./downloads")
if not os.path.exists(download_dir):
    os.makedirs(download_dir)

# 配置浏览器选项
chrome_options = Options()
prefs = {
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True
}
chrome_options.add_experimental_option("prefs", prefs)

# 创建浏览器实例
driver = webdriver.Chrome(options=chrome_options)
wait = WebDriverWait(driver, 10)

try:
    # 1. 上传文件
    driver.get("https://example.com/upload")
    
    # 找到并上传文件
    file_input = wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "input[type='file']"))
    )
    file_input.send_keys(os.path.abspath("./test_upload.txt"))
    
    # 点击上传按钮
    upload_button = driver.find_element(By.ID, "upload-btn")
    upload_button.click()
    
    # 等待上传完成
    wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "上传成功"))
    
    # 2. 下载文件
    download_link = wait.until(
        EC.element_to_be_clickable((By.ID, "download-link"))
    )
    download_link.click()
    
    # 等待下载完成
    def is_download_complete():
        # 检查是否有.crdownload临时文件
        for fname in os.listdir(download_dir):
            if fname.endswith('.crdownload'):
                return False
        return True
    
    wait.until(lambda driver: is_download_complete())
    
    # 获取下载的文件
    downloaded_files = [f for f in os.listdir(download_dir) 
                       if os.path.isfile(os.path.join(download_dir, f))]
    
    if downloaded_files:
        latest_file = max(downloaded_files, 
                         key=lambda f: os.path.getmtime(os.path.join(download_dir, f)))
        print(f"成功下载文件: {latest_file}")
        
        # 验证文件内容(如果需要)
        file_path = os.path.join(download_dir, latest_file)
        with open(file_path, 'r') as f:
            content = f.read()
            print(f"文件内容: {content[:100]}...")  # 只打印前100个字符
        
finally:
    driver.quit()

四、常见问题与解决方案

1. 下载对话框弹出

如果仍然看到下载对话框,确保正确设置了浏览器偏好设置:

python 复制代码
prefs = {
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,  # 关键设置
    # ...
}

2. 下载文件名为乱码

某些情况下,下载的文件名可能包含乱码。可以尝试重命名文件:

python 复制代码
import urllib.parse

# 从Content-Disposition头获取文件名(如果可用)
content_disposition = driver.execute_script(
    "return arguments[0].getAttribute('download')", download_link
)
if content_disposition:
    filename = urllib.parse.unquote(content_disposition)
    # 重命名文件
    latest_file = get_latest_downloaded_file(download_dir)
    os.rename(latest_file, os.path.join(download_dir, filename))

3. 处理大文件下载

对于大文件下载,可能需要增加超时时间:

python 复制代码
def wait_for_download_complete(download_dir, timeout=300):  # 5分钟超时
    # ... 实现同上

4. 清理下载目录

在测试开始前清理下载目录,避免旧文件干扰:

python 复制代码
import shutil

# 清理下载目录
if os.path.exists(download_dir):
    shutil.rmtree(download_dir)
os.makedirs(download_dir)

五、最佳实践

  1. 使用绝对路径:始终使用文件的绝对路径,避免相对路径可能带来的问题。

  2. 合理设置超时:根据文件大小和网络状况设置合理的超时时间。

  3. 验证下载内容:不仅检查文件是否存在,还应验证文件内容和大小。

  4. 清理测试环境:测试开始前清理下载目录,确保测试环境干净。

  5. 跨浏览器考虑:不同浏览器需要不同的配置,确保你的代码能处理这些差异。

  6. 错误处理:添加适当的异常处理,处理下载失败或超时的情况。

相关推荐
爱敲代码的菜菜8 小时前
【测试】自动化测试
css·selenium·测试工具·junit·自动化·xpath
123过去16 小时前
wireshark使用教程
linux·网络·测试工具·wireshark
123过去16 小时前
hexinject使用教程
linux·网络·测试工具
测试199817 小时前
功能测试、自动化测试、性能测试的区别?
自动化测试·软件测试·python·功能测试·测试工具·性能测试·安全性测试
爱敲代码的菜菜18 小时前
【测试】Selenium
selenium·测试工具·xpath·webdriver·cssselector
shughui1 天前
Fiddler下载、安装、使用、汉化,详细图文教程(2026附安装包)
前端·测试工具·fiddler
若惜2 天前
selenium自动化测试web自动化测试 框架封装Pom
前端·python·selenium
2501_915921432 天前
常用iOS性能测试工具大全及使用指南
android·测试工具·ios·小程序·uni-app·cocoa·iphone
半个俗人2 天前
3.postman全局变量和环境变量
测试工具·postman