大二dw网页设计作业成品,网站优化案例分析,电商网络推广怎么做,微商城 网站制作很多selenium学习者被浏览器弹出的文件上传、下载框折磨的痛不欲生#xff0c;今天博主就带你们轻松搞定上传和下载问题。上传上传弹框文件上传是所有UI自动化测试都要面对的一个头疼问题#xff0c;要处理这个问题#xff0c;我们需要#xff1a;首先#xff0c;要区分出…很多selenium学习者被浏览器弹出的文件上传、下载框折磨的痛不欲生今天博主就带你们轻松搞定上传和下载问题。上传上传弹框文件上传是所有UI自动化测试都要面对的一个头疼问题要处理这个问题我们需要首先要区分出上传按钮的种类大体上可以分为两种一种是input框另外一种就比较复杂通过js、flash等实现标签非input接下来我们分别对这两种进行分析1.input标签众所周知标签是可以直接send_keys的这里也不例外来看代码示例代码# -*- coding: utf-8 -*-from selenium import webdriverdriver webdriver.Firefox()driver.get(http://sahitest.com/demo/php/fileUpload.htm)upload driver.find_element_by_id(file)upload.send_keys(d:\\baidu.py) # send_keysprint upload.get_attribute(value) # check valuedriver.quit()结果baidu.py很明显对于input上传直接send_keys是最简单的解决方案。2.非input型上传接下来难度要升级了对于那些不是input框实现的上传怎么办这种上传千奇百怪有用a标签的有用div的有用button的有用object的我们没有办法通过直接在网页上处理掉这些上传唯一的办法就是打开OS弹框去处理弹框。问题又来了OS弹框涉及的层面已经不是selenium能解决的了怎么办很简单用OS层面的操作去处理呗到这里我们基本找到了问题的处理方法。大体上有以下几种解决方案autoIT借助外力我们去调用其生成的au3或exe文件。Python pywin32库识别对话框句柄进而操作SendKeys库keybd_event跟3类似不过是模拟按键ctrlactrlc ctrlv...目前我只知道以上四种办法有其他方法的请留言告诉我让我学习一下。我们依次看一下1. autoIT对于OS弹框上传、下载等均可以用 autoit 进行处理简单上传很简单博主这里还要交给你怎么通过传参对要传的文件进行参数化想要参数化传入的参数可以通过autoit的命令行参数D:\ myProg.exe param1 This is a string parameter 99在脚本中可用以下变量获取命令行参数$CmdLine[0] ; 3$CmdLine[1] ; param1$CmdLine[2] ; This is a string parameter$CmdLine[3] ; 99$CmdLineRaw ; param1 This is a string parameter 99$CmdLine[0] 获取的是命令行参数的总数在上例中$CmdLine[0]3$CmdLine[1]~$CmdLine[63] 获取的是命令行参数第1到第63位这个方式最多只能获取63个参数不过正常情况下是足够用的$CmdLineRaw 获取的是未拆分的所有参数是一个长字符串这种情况下不局限与63个参数下面我们小小实践一下通过autoit的获取对象并编辑脚本ControlFocus(文件上传, , Edit1)WinWait([CLASS:#32770], , 10)ControlSetText(文件上传 ,, Edit1, $CmdLine[1])Sleep(2000)ControlClick(文件上传, ,Button1);通过Aut2Exe工具将脚本转成exe文件(upfile.exe)我们先通过命令行试试打开网页上传弹框然后在cmd中执行该脚本D:\ upfile.exe D:\1.html成功接下来就是用Python用os模块来调用该文件了# -*- coding: utf-8 -*-from selenium import webdriverimport osimport timedriver webdriver.Firefox()driver.get(http://www.sahitest.com/demo/php/fileUpload.htm)driver.find_element_by_id(file).click()time.sleep(1)os.system(D:\\upfile.exe D:\\1.html) # 这里可以对传参进行参数化我们可以通过py脚本来控制所要上传的文件了time.sleep(3)driver.quit()执行成功接下来这里有个小问题要提醒你关于OS弹框的title不同浏览器是不一样的一般firefox是“文件上传”、chrome叫“打开”、而IE则叫“选择要加载的文件”对于这个问题你可以写三个不同脚本在处理弹框的方法中根据浏览器类型的不同而进行选择或者每次去获取所有类型弹框再或者通过参数传入该弹框的名称。具体怎么去应用就要考考你了。2.win32gui废话不多说上代码先代码# -*- coding: utf-8 -*-from selenium import webdriverimport win32guiimport win32conimport timedr webdriver.Firefox()dr.get(http://sahitest.com/demo/php/fileUpload.htm)upload dr.find_element_by_id(file)upload.click()time.sleep(1)# win32guidialog win32gui.FindWindow(#32770, u文件上传) # 对话框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) # 确定按钮Buttonwin32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, d:\\baidu.py) # 往输入框输入绝对地址win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) # 按buttonprint upload.get_attribute(value)dr.quit()结果baidu.py在这里你需要一个非常重要的小工具Spy百度一下有很多当然你也可以用autoIT自带的工具不过没有这个好用建议去下一个吧。而且你得安装pywin32的库你可以到安装完成之后在【开始菜单Python的文件夹】里看到PyWin32的文档【Python for Windows Documentation】你能从中找到对应的方法API。简单介绍几个用到的win32gui.FindWindow(lpClassNameNone, lpWindowNameNone):自顶层窗口开始寻找匹配条件的窗口并返回这个窗口的句柄。lpClassName类名在Spy里能够看到lpWindowName窗口名标题栏上能看到的名字代码示例里我们用来寻找上传窗口你可以只用其中的一个用classname定位容易被其他东西干扰用windowname定位不稳定不同的上传对话框可能window_name不同怎么定位取决于你的情况。win32gui.FindWindowEx(hwndParent0, hwndChildAfter0, lpszClassNone, lpszWindowNone)搜索类名和窗体名匹配的窗体并返回这个窗体的句柄。找不到就返回0。hwndParent若不为0则搜索句柄为hwndParent窗体的子窗体。hwndChildAfter若不为0则按照z-index的顺序从hwndChildAfter向后开始搜索子窗体否则从第一个子窗体开始搜索。lpClassName字符型是窗体的类名这个可以在Spy里找到。lpWindowName字符型是窗口名也就是标题栏上你能看见的那个标题。代码示例里我们用来层层寻找输入框和寻找确定按钮win32gui.SendMessage(hWnd, Msg, wParam, lParam)hWnd整型接收消息的窗体句柄Msg整型要发送的消息这些消息都是windows预先定义好的可以参见系统定义消息(System-Defined Messages)wParam整型消息的wParam参数lParam整型消息的lParam参数代码示例里我们用来向输入框输入文件地址以及点击确定按钮至于win32ui模块以及其他的方法这里不进行更多描述想要了解的自行百度或看pywin32文档。3.SendKeys首先要安装SendKeys库可以用pip安装pip install SendKeys代码示例代码# -*- coding: utf-8 -*-from selenium import webdriverimport win32guiimport win32conimport timedr webdriver.Firefox()dr.get(http://sahitest.com/demo/php/fileUpload.htm)upload dr.find_element_by_id(file)upload.click()time.sleep(1)# SendKeysSendKeys.SendKeys(D:\\baidu.py) # 发送文件地址SendKeys.SendKeys({ENTER}) # 发送回车键print upload.get_attribute(value)dr.quit()结果baidu.py通过SendKeys库可以直接向焦点里输入信息不过要注意在打开窗口是略微加一点等待时间否则容易第一个字母send不进去(或者你可以在地址之前加一个无用字符)不过我觉得这种方法很不稳定不推荐。4.keybd_eventwin32api提供了一个keybd_event()方法模拟按键不过此方法比较麻烦也不稳定所以很不推荐下面给出部分代码示例如果想要研究自己百度去学习吧。...# 先找一个input框输入想要上传的文件的地址剪切到剪贴板video.send_keys(C:\\Users\\Administrator\\Pictures\\04b20919fc78baf41fc993fd8ee2c5c9.jpg)video.send_keys(Keys.CONTROL, a) # selenium的send_keys(ctrla)video.send_keys(Keys.CONTROL, x) # (ctrlx)driver.find_element_by_id(uploadImage).click() # 点击上传按钮打开上传框# 粘贴(ctrl v)win32api.keybd_event(17, 0, 0, 0) # 按下按键 ctrlwin32api.keybd_event(86, 0, 0, 0) # 按下按键 vwin32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0) # 升起按键 vwin32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0) # 升起按键 ctrltime.sleep(1)# 回车(enter)win32api.keybd_event(13, 0, 0, 0) # 按下按键 enterwin32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0) # 升起按键 enter...是不是很麻烦当然你甚至可以用按键把整个路径输入进去不过我想没人愿意这么做的。而且在此过程中你不能随意移动鼠标不能使用剪贴板太不稳定了所以非常不建议你用这种办法。。3.多文件上传接下来还有一种情况值得我们考虑那就是多文件上传。如何上传多个文件当然我们还是往输入框里输入文件路径所以唯一要搞清楚的就是多文件上传时文件路径是怎么写的。我来告诉你吧多文件上传就是在文件路径框里用引号括起单个路径然后用逗号隔开多个路径就是这么简单例如D:\\a.txt D:\\b.txt但需要注意的是只有多个文件在同一路径下才能这样用否则是会失败的(下面的写法是不可以的)C:\\a.txt D:\\b.txt接下里找一个例子试试代码# -*- coding: utf-8 -*-from selenium import webdriverimport win32guiimport win32conimport timedr webdriver.Firefox()dr.get(http://www.sucaijiayuan.com/api/demo.php?url/demo/20150128-1)dr.switch_to.frame(iframe) # 一定要注意framedr.find_element_by_class_name(filePicker).click()time.sleep(1)dialog win32gui.FindWindow(#32770, None)ComboBoxEx32 win32gui.FindWindowEx(dialog, 0, ComboBoxEx32, None)ComboBox win32gui.FindWindowEx(ComboBoxEx32, 0, ComboBox, None)Edit win32gui.FindWindowEx(ComboBox, 0, Edit, None)button win32gui.FindWindowEx(dialog, 0, Button, None)# 跟上面示例的代码是一样的只是这里传入的参数不同如果愿意可以写一个上传函数把上传功能封装起来win32gui.SendMessage(Edit, win32con.WM_SETTEXT, 0, d:\\baidu.py d:\\upload.py d:\\1.html)win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)print dr.find_element_by_id(status_info).textdr.quit()结果选中3张文件共1.17KB。可见多文件上传并没有那么复杂也很简单唯一的区别就是输入的参数不同而已。autoIT也可以实现有兴趣可以自己试试。而且我们可以发现一点就是上面的这个窗口的代码跟之前示例中的基本是一样说明我们可以把上传的部分抽出来写一个函数这样每次要上传直接去调用函数传入参数即可。看上传其实很好处理你有什么好的办法也可以给博主留言共同交流。下载下载弹框接下来我们看看文件下载很多人不会处理弹出的文件下载框。其实跟上传类似可以用autoit和win32api解决方法类似我们不在举例了可以根据上面所讲的上传来改写。这里博主想讲讲一种更漂亮的处理办法那就是指定下载路径不弹出弹框直接下载到指定路径。主要针对Firefox和Chrome浏览器其他浏览器未曾去寻找这方面的资料。Firefox 文件下载对于Firefox需要我们设置其Profilebrowser.download.dir指定下载路径browser.download.folderList设置成 2 表示使用自定义下载路径设置成 0 表示下载到桌面设置成 1 表示下载到默认路径browser.download.manager.showWhenStarting在开始下载时是否显示下载管理器browser.helperApps.neverAsk.saveToDisk对所给出文件类型不再弹出框进行询问下面来个示例# -*- coding: utf-8 -*-from selenium import webdriverfrom time import sleepprofile webdriver.FirefoxProfile()profile.set_preference(browser.download.dir, d:\\)profile.set_preference(browser.download.folderList, 2)profile.set_preference(browser.download.manager.showWhenStarting, False)profile.set_preference(browser.helperApps.neverAsk.saveToDisk, application/zip)driver webdriver.Firefox(firefox_profileprofile)driver.get(http://sahitest.com/demo/saveAs.htm)driver.find_element_by_xpath(//a[text()testsaveas.zip]).click()sleep(3)driver.quit()Firefox需要针对每种文件类型进行设置这里需要我们查询对应文件的MIME类型可以用以下链接进行查询MIME 参考手册Chrome 文件下载Chrome浏览器类似设置其optionsdownload.default_directory设置下载路径profile.default_content_settings.popups设置为 0 禁止弹出窗口它的设置就简单多了看个示例# -*- coding: utf-8 -*-from selenium import webdriverfrom time import sleepoptions webdriver.ChromeOptions()prefs {profile.default_content_settings.popups: 0, download.default_directory: d:\\}options.add_experimental_option(prefs, prefs)driver webdriver.Chrome(executable_pathD:\\chromedriver.exe, chrome_optionsoptions)driver.get(http://sahitest.com/demo/saveAs.htm)driver.find_element_by_xpath(//a[text()testsaveas.zip]).click()sleep(3)driver.quit()看文件下载也很简单吧。如果你还有任何想法欢迎给博主留言。更多关于python selenium的文章请关注我的CSDN专栏