进行web自动化的时候,文件上传是很常见的操作。

在selenium中,文件上传可以分为两种场景:

  • input标签:这种可以用selenium提供的send_keys()方法轻松解决;
  • 非input标签:实现起来比较困难,可以借助第三方库pypiwin32或者SendKeys第三方库或者AutoIt 去调用它生成的au3或者exe格式的文件

input标签:send_keys()方法

比如,著名的在线图片压缩网站: https://tinypng.com/

通常,网站页面上传文件的功能,是通过 type 属性 为 file 的 HTML input 元素实现的。

如下所示:

<input type="file" multiple="multiple">

使用selenium自动化上传文件,我们只需要定位到该input元素,然后通过 send_keys 方法传入要上传的文件路径即可。

如下所示:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/23 16:20
# @Author  : shisuiyi
# @File    : upload.py
# @Software: win10 Tensorflow1.13.1 python3.9
from selenium import webdriver

driver = webdriver.Chrome()
# input标签的html文件
driver.get('https://tinypng.com/')
file_ele = driver.find_element('xpath', "//input[@type='file']")
# 上传本地图片
file_ele.send_keys(r"C:\Users\12446\Pictures\1.png")

如果需要上传多个文件,可以多次调用send_keys,如下

file_ele = driver.find_element('xpath', "//input[@type='file']")
# 上传本地图片
file_ele.send_keys(r"C:\Users\12446\Pictures\1.png")
file_ele.send_keys(r"C:\Users\12446\Pictures\2.png")

非input标签:pypiwin32

网站示例:https://pearocr.com/#/

执行

pip install pypiwin32

确保 pypiwin32已经安装,然后参考如下示例代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/23 16:20
# @Author  : shisuiyi
# @File    : upload.py
# @Software: win10 Tensorflow1.13.1 python3.9
from time import sleep
from selenium import webdriver
import win32com.client

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://pearocr.com/#/")
driver.maximize_window()
# 找到选择文件元素
file_ele = driver.find_element('xpath', "(//i[@class='notranslate material-icons-outlined q-icon'])[2]")
file_ele.click()
sleep(2)  # 等待上传选择文件对话框打开

# 直接发送键盘消息给 当前应用程序,
# 前提是浏览器必须是当前应用
shell = win32com.client.Dispatch("WScript.Shell")

# 输入文件路径,最后的'\n',表示回车确定,也可能时 '\r' 或者 '\r\n'
shell.Sendkeys(r"C:\Users\12446\Pictures\1.png" + '\r\n')
sleep(1)

非input标签:WinSpy工具

网站示例:https://pearocr.com/#/

  1. 安装pypiwin32, 使用命令 pip install pypiwin32
  2. 下载WinSpy包,解压后,双击可执行文件即可
  3. 点击选择文件,会出现一个上传文件的弹窗
  4. 打开安装好的WinSpy,选中按钮拖拽到文件名的输入框中,WinSpy会对应出现相关信息
  5. 选择WinSpy底部按钮Tree, 查看弹窗按钮的层级关系
    winspy.png
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/23 16:20
# @Author  : shisuiyi
# @File    : upload.py
# @Software: win10 Tensorflow1.13.1 python3.9
from time import sleep
import win32gui
import win32con
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://pearocr.com/#/")
driver.maximize_window()
# 找到选择文件元素
file_ele = driver.find_element('xpath', "(//i[@class='notranslate material-icons-outlined q-icon'])[2]")
file_ele.click()
sleep(2)  # 等待上传选择文件对话框打开

# #32770--对话框名字,即最外层整个弹窗
dialog = win32gui.FindWindow('#32770', '打开')
ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)
# 上面三行代码依次寻找对象,直到找到文件名输入框Edit对象的句柄

# 找到打开按钮
button = win32gui.FindWindowEx(dialog, 0, 'Button', None)
sleep(3)
# 发送本地文件
win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, r"C:\Users\12446\Pictures\1.png")
sleep(3)
# 点击打开按钮
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)
sleep(3)

如果想批量上传文件呢,修改发送本地文件的代码如下:

win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, r'"C:\Users\12446\Pictures\1.png" "C:\Users\12446\Pictures\2.png"')

非input标签:AutoIt工具

网站示例:https://pearocr.com/#/

下载AutoIT

进入官网https://www.autoitscript.com/site/autoit/downloads/

安装时参考 https://blog.csdn.net/yoyocat915/article/details/81106266
没有坑。

查看安装结果,这几个是我们需要用到的:

  • AutoIt Windows Info 用于识别Windows控件信息
  • Compile Script to.exe 用于将AutoIt生成 exe 执行文件
  • SciTE Script Editor 用于编写AutoIt脚本
  • Run Script 用于执行AutoIt脚本

识别元素

打开AutoIt Windows Info,将Finder Tool拖拽到按钮上

Snipaste_20220123_183450.png

获取到如下属性信息:

  • Title = “打开"
  • Class = Button
  • Instance = 1

利用这些信息就可以编写脚本了

编写脚本

脚本语法如下

ControlFocus ( "窗口标题", "窗口文本", 控件ID)  设置输入焦点到指定窗口的某个控件上

WinWait ( "窗口标题" [, "窗口文本" [, 超时时间]] ) 暂停脚本的执行直至指定窗口存在(出现)为止

ControlSetText ( "窗口标题", "窗口文本", 控件ID, "新文本" )  修改指定控件的文本

Sleep ( 延迟 )  使脚本暂停指定时间段

ControlClick ( "窗口标题", "窗口文本", 控件ID [, 按钮] [, 点击次数] )  向指定控件发送鼠标点击命令

其中,title即AutoIt Window Info识别出的Title字段,controlID即AutoIt Window Info识别出的Class和Instance的拼接,如上图拼接后的结果应为:Button1

ControlFocus("打开", "","Edit1")

WinWait("[CLASS:#32770]","",10)

ControlSetText("打开", "", "Edit1","你的路径\XXXX.jpg")

Sleep(2000)

ControlClick("打开", "","Button1");

保存脚本文件后,点击Tool -> Go,可以看到文件上传被自动执行了。

Snipaste_20220123_184423.png

附加:参数化路径

如果将路径变为参数,上传文件会变得更方便,可以使用$CmdLine来获得输入的参数,将原来的路径修改即可。

ControlFocus("打开", "","Edit1")

WinWait("[CLASS:#32770]","",10)

ControlSetText("打开", "", "Edit1",$CmdLine[1])

Sleep(2000)

ControlClick("打开", "","Button1");

3.4 打包成exe

使用Compile Script to.exe工具,将脚本生成为exe可执行文件。我打包好的文件名叫upload.exe

Snipaste_20220123_184909.png

python中调用脚本

使用os.system模拟命令行输入来调用脚本,由于路径已经参数化,因此下面的代码中可以随时修改路径。如果使用带有\的路径的话,一定要在字符串前面加上r。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/23 16:20
# @Author  : shisuiyi
# @File    : upload.py
# @Software: win10 Tensorflow1.13.1 python3.9
from time import sleep
import os
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://pearocr.com/#/")
driver.maximize_window()
# 找到选择文件元素
file_ele = driver.find_element('xpath', "(//i[@class='notranslate material-icons-outlined q-icon'])[2]")
file_ele.click()
sleep(2)  # 等待上传选择文件对话框打开

pic_path = r'C:\Users\12446\Pictures\1.png'
os.system(r'D:\Lemon\作业\upload.exe %s' % pic_path)
sleep(10)