Selenium4Web自动化7-文件上传和日期控件
一、文件上传操作-input标签文件选择
当input元素为文件类型时, 文件上传对话框可以使用Selenium处理. 文件上传的代码实现如下
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.implicitly_wait(10)
driver.get("https://the-internet.herokuapp.com/upload");
driver.find_element(By.ID,"file-upload").send_keys("selenium-snapshot.jpg")
driver.find_element(By.ID,"file-submit").submit()
if(driver.page_source.find("File Uploaded!")):
print("file upload success")
else:
print("file upload not successful")
driver.quit()
二、文件上传操作-非input标签文件选择
当上传文件按钮不是input标签时,比如下图的前端框架layui(一个JS框架)上传按钮就是button标签,selenium无法处理文件上传。
那么对于那些不是input框实现的上传怎么办,这种上传千奇百怪,有用a标签的,有用div的,有用button的,有用object的,我们没有办法通过直接在网页上处理掉这些上传,唯一的办法就是打开windows的系统弹框,去处理弹框。
解决办法很简单,用OS层面的操作去处理。这里经过多种库的调用,找到一个适用性最好,学习起来最简单的库PyAutoGui来解决上传问题。
当然网上还有很多方法,有兴趣的可以去看看,这里贴一下链接,对比下来就会知道PyAutoGui才是更简单易用以及实用的解决方案。
Selenium+Python上传文件方法:
https://www.jianshu.com/p/fba37cc5d5e2
1. PyAutoGui入门
官方文档链接:
https://pyautogui.readthedocs.io/en/latest/
PyAutoGUI 让您的 Python 脚本控制鼠标和键盘以自动与其他应用程序交互。API 的设计很简单。PyAutoGUI 适用于 Windows、macOS 和 Linux,并在 Python 2 和 3 上运行。
要使用 pip 安装:pip install pyautogui
PyAutoGUI 有如下几块功能:
移动鼠标并单击其他应用程序的窗口。
向应用程序发送击键(例如,填写表格)。
截取屏幕截图,并给出一个图像(例如,一个按钮或复选框),然后在屏幕上找到它。
找到应用程序的窗口,然后移动、调整大小、最大化、最小化或关闭它(目前仅限 Windows)。
显示警报和消息框。
1.1 入门代码案例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyautogui
from time import sleep
# Get the size of the primary monitor.
# 获取主监视器的大小
# screenWidth, screenHeight = pyautogui.size()
# print(screenWidth, screenHeight)
#
# # Get the XY position of the mouse.
# # 获得鼠标的XY坐标(演示的是扩展屏,所以X坐标>1920了)
# currentMouseX, currentMouseY = pyautogui.position()
# print(currentMouseX, currentMouseY)
#
# # Move the mouse to XY coordinates.
# # 移动鼠标到指定的坐标
# pyautogui.moveTo(3800, 613)
#
# # Click the mouse.
# # 点击鼠标
# pyautogui.click()
#
# # Move the mouse to XY coordinates and click it.
# # 移动鼠标到坐标然后点击
# pyautogui.click(3800, 513)
#
# # Find where button.png appears on the screen and click it.
# # 找到桌面上名为button.png的图片并点击
# # 代码测试会报错:TypeError: cannot unpack non-iterable NoneType object
# # pyautogui.Click('button.png')
#
# # Move the mouse 400 pixels to the right of its current position.
# # 从当前位置右移鼠标400PX
# pyautogui.move(400, 0)
#
# # Double click the mouse.
# # 双击鼠标
# pyautogui.doubleClick()
#
# # Use tweening/easing function to move mouse over 2 seconds.
# # 使用渐变/缓动功能移动鼠标,间隔2秒。
# # 坐标是目标坐标,从当前位置移动过去,2秒停顿一下(方便看移动过程)
# pyautogui.moveTo(500, 500, duration=2, tween=pyautogui.easeInOutQuad)
# type with quarter-second pause in between each key
# 输入文本,每次按键间隔0.25秒
# 案例:新建txt文档演示
# pyautogui.write('Hello world!', interval=0.25)
# Press the Esc key. All key names are in pyautogui.KEY_NAMES
# 案例:选中代码然后取消
# pyautogui.press('esc')
# pyautogui.KEY_NAMES
# Press the Shift key down and hold it.
# 按下Shift键不放
# with pyautogui.hold('shift'):
# # Press the left arrow key 4 times.
# # 按左键4次
# pyautogui.press(['left', 'left', 'left', 'left']) # Press the left arrow key 4 times.
# Shift键会自动释放
# Shift key is released automatically.
# Press the Ctrl-C hotkey combination.
# 按Ctrl-C组合键
# pyautogui.hotkey('ctrl', 'c')
# Make an alert box appear and pause the program until OK is clicked.
# 生成一个弹窗并暂停程序,直到点击Ok按钮
# pyautogui.alert('This is the message to display.')
1.2 例子,在画图中以方形螺旋拖动鼠标
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyautogui
from time import sleep
sleep(5)
distance = 200
while distance > 0:
pyautogui.drag(distance, 0, duration=0.5) # 右移
distance -= 5
pyautogui.drag(0, distance, duration=0.5) # 下移
pyautogui.drag(-distance, 0, duration=0.5) # 左移
distance -= 5
pyautogui.drag(0, -distance, duration=0.5) # 上移
1.3 应用PyAutoGui实现文件上传
通过直接操控鼠标键盘,是很容易实现文件上传的,只要能快速获得坐标即可,下面的代码可以实时获取鼠标的坐标
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import time
import pyautogui as pag
try:
while True:
print("Press Ctrl-C to end")
screenWidth, screenHeight = pag.size() #获取屏幕的尺寸
print(screenWidth,screenHeight)
x,y = pag.position() #获取当前鼠标的位置
# Python rjust() 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串。
# 如果指定的长度小于字符串的长度则返回原字符串。
posStr = "Position:" + str(x).rjust(4)+','+str(y).rjust(4)
print(posStr)
time.sleep(0.2)
os.system('cls') #清除屏幕
except KeyboardInterrupt:
print('end....')
如下图,运行代码后,不要停,控制台会实时输出鼠标所在位置的坐标,类似于页面元素定位了,只是这里换成了坐标。
有了坐标,就可控制鼠标和键盘在屏幕中的指定位置进行文件上传操作了。
三、日期控件
1 可输入日期控件
一般的日期控件是可以直接输入日期的,如果使用webdriver 去设置日期,
- 定位到该日期控件
- 使用sendKeys 方法
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from time import sleep
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
driver.get("https://layuion.com/demo/laydate.html")
# 移动窗口
driver.set_window_position(1900,-200)
driver.set_window_size(1550,1000)
# 定位到日期控件,并输入
locator = (By.XPATH,'//input[@id="test1"]')
wait.until(ec.visibility_of_element_located(locator)).send_keys("2022-09-30")
2 readonly日期控件
有的日期控件是readonly的
比如:
<input class="form-control getTime ng-touched valid ng-valid-parse ng-valid ng-valid-required ng-pristine" type="text" required="" name="establish_time" ng-model="addStationInfo.establish_time" ng-readonly="true" readonly="readonly"/>
这个时候,没法调用WebElement的sendKeys()
方法1:可以使用JS remove readonly attribute,然后sendKeys
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
"""
<input class="form-control getTime ng-touched valid ng-valid-parse ng-valid ng-valid-required ng-pristine"
type="text" required="" name="establish_time" ng-model="addStationInfo.establish_time" ng-readonly="true"
readonly="readonly"/>
"""
js = 'document.getElementByName("establish_time").removeAttribute("readonly")'
driver.execute_script(js)
# 在sendKeys之前应该清空原来的默认值
driver.find_element(By.NAME,"establish_time").clear()
driver.find_element(By.NAME,"establish_time").send_keys("2033-08-03")
如果输入完日期,并无法触发查询动作,可以点击日期输入框,调出日历控件,点击“确认”按钮,即可触发
方法2:使用js方法,输入日期,直接改掉输入框元素的值即可
#去掉元素的readonly属性
js = 'document.getElementByName("establish_time").removeAttribute("readonly");'
driver.execute_script(js)
#使用js方法输入日期
js_value = 'document.getElementByName("establish_time").value = "2020-05-28"'
driver.execute_script(js_value)
目前很少有使用readonly的日期控件了,没有相应的案例。
3 日期控件在frame里
操作思路:
1、切换到iframe;
2、完成相关操作;
3、返回主文档
iframes=browser.find_elements_by_css_selector('iframe')
browser.switch_to.frame(iframes[0])
ny=browser.find_element_by_xpath('//*[@id="ny"]')
ny.click()
time.sleep(1)
ny.send_keys('202106')
time.sleep(1)
#从frame中切回主文档
browser.switch_to.default_content()
4 非readonly,也无法直接输入的日期控件
这种,基本只能靠鼠标点击和鼠标滚动日期控件来完成了。会存在一些看不到的元素,就要用到最新学到的Selenium4的滚轮
如上图,最下面的23时和59分、59秒,都是不可见的,需要滚动到下面
# 修改分钟,改成59
locater = (By.XPATH,"//p[contains(text(),'分')]/../ol/li[60]")
# 基于元素,按给点数值滚动
min = driver.find_element(By.XPATH, "//p[contains(text(),'分')]/../ol")
# 定义滚动起始元素
scroll_origin = ScrollOrigin.from_element(min)
min59 = driver.find_element(*locater)
# 按住不动,滚动指定数值成功
ActionChains(driver) \
.scroll_to_element(min)\
.click_and_hold(min)\
.scroll_from_origin(scroll_origin,0,1800) \
.release(min)\
.move_to_element(min59)\
.click()\
.perform()
如果ActionChains不能解决问题,还可以考虑使用PyAutoGui,用坐标进行定位并点击。
本文来自博客园,作者:测试老宅男扶摇,转载请注明原文链接:https://www.cnblogs.com/cekailsf/p/16821589.html