Selenium+Python上傳文件方法大全

文件上傳是做UI自動(dòng)化測(cè)試時(shí)候的一個(gè)大問(wèn)題谤绳,嘗試了一下網(wǎng)上各種上傳文件的方式,以下試驗(yàn)按照使用頻率來(lái)排名。(多個(gè)方法多個(gè)思路闷供,你要不想學(xué)“茴”字的四種寫(xiě)法烟央,看第一個(gè)就夠了)

孔乙己茴香豆.jpg

環(huán)境準(zhǔn)備:

  • 一個(gè)可以帶有上傳文件按鈕的網(wǎng)頁(yè)(把以下代碼拷貝到一個(gè)新建文本文檔中,可以取名為fileupload.html)
 <html>

<body>

<form name="form1" action="fileUpload.php" method="post" enctype="multipart/form-data">
<label for="file">File:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="hidden" name="multi" value="false"/>
<input type="submit" name="submit" value="Submit Single" />
</form>


<form action="fileUpload.php" method="post" enctype="multipart/form-data">
<label for="file2">File[]:</label>
<input type="file" name="file[]" id="file2" /> 
<br />
<label for="file3">File[]:</label>
<input type="file" name="file[]" id="file3" /> 
<br />
<input type="hidden" name="multi" value="true"/>
<input type="submit" name="submit" value="Submit Array" />
</form>

<script>
function setAction(){
    document.form2.action = "fileUpload.php";
}
</script>

<form name="form2" action="" method="post" enctype="multipart/form-data" onsubmit="setAction()">
<label for="file">File:</label>
<input type="file" name="file" id="file4" /> 
<br />
<input type="hidden" name="multi" value="false"/>
<input type="submit" name="submit" value="Submit Single" />
</form>

</body>
</html>
  • 把這個(gè)文件扔到xampp的/htdocs/test目錄下(test目錄是自己建的)
12.png

在動(dòng)手之前歪脏,我們要區(qū)分出上傳按鈕的種類(lèi)疑俭,大體上可以分為兩種

  • 一種是input框
  • 另外一種就比較復(fù)雜,通過(guò)js婿失、flash等實(shí)現(xiàn)钞艇,標(biāo)簽非input

我們分別對(duì)這兩種進(jìn)行分析:
1.input標(biāo)簽
眾所周知,input標(biāo)簽是可以直接send_keys的豪硅,這種情況下就簡(jiǎn)單粗暴(專(zhuān)一 一點(diǎn)哩照,這種已經(jīng)就很好了),來(lái)看代碼示例:

from selenium import webdriver
import time

driver = webdriver.Firefox()
driver.get('http://localhost/test/fileupload.html')
upload = driver.find_element_by_id('file')
time.sleep(12)
upload.send_keys('d:\\all_money.wmv')  # send_keys
print (upload.get_attribute('value'))  # check value

driver.quit()

控制臺(tái)結(jié)果輸出:

"C:\Program Files\Python35-32\python.exe" D:/Python/Demo/fileupload.py
all_money.wmv

2.非input型上傳

那么對(duì)于那些不是input框?qū)崿F(xiàn)的上傳怎么辦懒浮,這種上傳千奇百怪飘弧,有用a標(biāo)簽的,有用div的砚著,有用button的次伶,有用object的,我們沒(méi)有辦法通過(guò)直接在網(wǎng)頁(yè)上處理掉這些上傳稽穆,唯一的辦法就是打開(kāi)windows的系統(tǒng)彈框冠王,去處理彈框。

問(wèn)題又來(lái)了舌镶,Selenium2.0還不能解決掉windows系統(tǒng)彈框的問(wèn)題柱彻,怎么辦?很簡(jiǎn)單餐胀,用OS層面的操作去處理唄(誰(shuí)家的孩子誰(shuí)家領(lǐng)回家的思維方式在哪里都好用)

大體上有以下四種解決方案:

  • Python pywin32庫(kù)哟楷,識(shí)別對(duì)話(huà)框句柄,進(jìn)而操作
  • SendKeys庫(kù)
  • autoIT否灾,借助外力吓蘑,我們?nèi)フ{(diào)用其生成的au3或exe文件。
  • keybd_event坟冲,跟第一種類(lèi)似磨镶,不過(guò)是模擬按鍵,ctrl+a健提,ctrl+c琳猫, ctrl+v…
    目前只知道以上四種辦法,有其他方法的請(qǐng)留言私痹,歡迎拍磚和討論脐嫂。

NO 1:pywin32庫(kù)
1 首先安裝pywin32庫(kù)(命令:pip install pywin32)
2 代碼示例

from selenium import webdriver
import win32gui
import win32con
import time

dr = webdriver.Firefox()
dr.get('http://localhost/test/fileupload.html')
upload = dr.find_element_by_id('file')
upload.click()
time.sleep(1)

# win32gui
dialog = win32gui.FindWindow('#32770', '文件上傳')  # 對(duì)話(huà)框
ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)  # 上面三句依次尋找對(duì)象统刮,直到找到輸入框Edit對(duì)象的句柄
button = win32gui.FindWindowEx(dialog, 0, 'Button', None)  # 確定按鈕Button

win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, 'd:\\all_money.wmv')  # 往輸入框輸入絕對(duì)地址
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 按button

print (upload.get_attribute('value'))
dr.quit()

控制臺(tái)結(jié)果輸出:

"C:\Program Files\Python35-32\python.exe" D:/Python/Demo/fileupload.py
all_money.wmv

這個(gè)地方大家其實(shí)對(duì)識(shí)別對(duì)話(huà)框的句柄有問(wèn)題,這個(gè)在使用autoIt的時(shí)候可以解決掉,或者使用Spy++這個(gè)小工具账千。其它的也就是win32gui里面的api調(diào)用方式侥蒙。

常用的:

win32gui.FindWindow(lpClassName=None, lpWindowName=None):

自頂層窗口開(kāi)始尋找匹配條件的窗口,并返回這個(gè)窗口的句柄匀奏。
lpClassName:類(lèi)名鞭衩,在Spy++里能夠看到
lpWindowName:窗口名,標(biāo)題欄上能看到的名字
代碼示例里我們用來(lái)尋找上傳窗口娃善,你可以只用其中的一個(gè)论衍,用classname定位容易被其他東西干擾,用windowname定位不穩(wěn)定聚磺,不同的上傳對(duì)話(huà)框可能window_name不同坯台,怎么定位取決于你的情況。

win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None)

搜索類(lèi)名和窗體名匹配的窗體瘫寝,并返回這個(gè)窗體的句柄蜒蕾。找不到就返回0。
hwndParent:若不為0焕阿,則搜索句柄為hwndParent窗體的子窗體滥搭。
hwndChildAfter:若不為0,則按照z-index的順序從hwndChildAfter向后開(kāi)始搜索子窗體捣鲸,否則從第一個(gè)子窗體開(kāi)始搜索。
lpClassName:字符型闽坡,是窗體的類(lèi)名栽惶,這個(gè)可以在Spy++里找到。
lpWindowName:字符型疾嗅,是窗口名外厂,也就是標(biāo)題欄上你能看見(jiàn)的那個(gè)標(biāo)題。
代碼示例里我們用來(lái)層層尋找輸入框和尋找確定按鈕

win32gui.SendMessage(hWnd, Msg, wParam, lParam)

hWnd:整型代承,接收消息的窗體句柄
Msg:整型汁蝶,要發(fā)送的消息,這些消息都是windows預(yù)先定義好的论悴,可以參見(jiàn)系統(tǒng)定義消息(System-Defined Messages)
wParam:整型掖棉,消息的wParam參數(shù)
lParam:整型,消息的lParam參數(shù)
代碼示例里我們用來(lái)向輸入框輸入文件地址以及點(diǎn)擊確定按鈕膀估。

NO 2:AutoIt
對(duì)于OS彈框幔亥,上傳、下載等察纯,均可以用 autoit 進(jìn)行處理帕棉,同時(shí)還可以通過(guò)傳參對(duì)要傳的文件進(jìn)行參數(shù)化:

想要參數(shù)化傳入的參數(shù)针肥,可以通過(guò)autoit的命令行參數(shù):

D:\ uploadfile.exe param1 "This is an int parameter" 102

在腳本中,可用以下變量獲取命令行參數(shù):

$CmdLine[0] ; = 3
$CmdLine[1] ; = param1
$CmdLine[2] ; = "This is an int parameter"
$CmdLine[3] ; = 102
$CmdLineRaw ; = 'param1 "This is a string parameter" 99'

$CmdLine[0] 獲取的是命令行參數(shù)的總數(shù)香伴,在上例中參數(shù)有3個(gè)慰枕。

$CmdLine[1]~$CmdLine[63] 獲取的是命令行參數(shù)第1到第63位,這個(gè)方式最多只能獲取63個(gè)參數(shù)即纲,不過(guò)正常情況下是足夠用的

$CmdLineRaw 獲取的是未拆分的所有參數(shù)具帮,是一個(gè)長(zhǎng)字符串,這種情況下不局限與63個(gè)參數(shù)

通過(guò)autoit的獲取對(duì)象并編輯腳本:

ControlFocus("文件上傳", "", "Edit1")
WinWait("[CLASS:#32770]", "", 10)
ControlSetText("文件上傳" ,"", "Edit1", $CmdLine[1])
Sleep(2000)
ControlClick("文件上傳", "","Button1");

通過(guò)Aut2Exe工具將腳本轉(zhuǎn)成exe文件(uploadfile.exe)
接著就可以使用Python中的os模塊來(lái)運(yùn)行這個(gè)exe執(zhí)行程序了崇裁。

# -*- coding: utf-8 -*-
from selenium import webdriver
import os
import time

driver = webdriver.Firefox()
driver.get('http://localhost/test/fileupload.html')
driver.find_element_by_id('file').click()
time.sleep(1)

os.system('D:\\Python\\Demo\\uploadfile.exe "d:\\all_money.wmv" ')  # 這里可以對(duì)傳參進(jìn)行參數(shù)化匕坯,我們可以通過(guò)py腳本來(lái)控制所要上傳的文件了

time.sleep(3)
driver.quit()

執(zhí)行效果如下:

uploadcamrec.gif

注意點(diǎn):關(guān)于OS彈框的title,不同瀏覽器是不一樣的拔稳,一般firefox是“文件上傳”葛峻、chrome叫“打開(kāi)”、而IE則叫“選擇要加載的文件”巴比,對(duì)于這個(gè)問(wèn)題术奖,你可以寫(xiě)三個(gè)不同腳本,在處理彈框的方法中根據(jù)瀏覽器類(lèi)型的不同而進(jìn)行選擇轻绞,或者每次去獲取所有類(lèi)型彈框采记,再或者通過(guò)參數(shù)傳入該彈框的名稱(chēng)。

NO 3:Sendkeys庫(kù)
通過(guò)SendKeys庫(kù)可以直接向焦點(diǎn)里輸入信息政勃,不過(guò)要注意在打開(kāi)窗口是略微加一點(diǎn)等待時(shí)間唧龄,否則容易第一個(gè)字母send不進(jìn)去(或者你可以在地址之前加一個(gè)無(wú)用字符),這種方法很不穩(wěn)定奸远,不推薦既棺。

NO 4:keybd_event
win32api提供了一個(gè)keybd_event()方法模擬按鍵,不過(guò)此方法比較麻煩懒叛,也不穩(wěn)定丸冕,所以很不推薦


進(jìn)階版:
剛才的幾種方法都是上傳單個(gè)的文件的操作,如果我想上傳多個(gè)文件怎么辦呢薛窥?
答案很簡(jiǎn)單:

多文件上傳就是在文件路徑框里用引號(hào)括起單個(gè)路徑胖烛,然后用空格隔開(kāi)多個(gè)路徑,例如:
“D:\allmoney.txt” “D:\allgirls.txt”
注意點(diǎn)為:所有文件最好放于同一路徑下诅迷,才能這樣用佩番,否則是會(huì)失敗的。(這個(gè)還沒(méi)找到合適的網(wǎng)站測(cè)試罢杉,稍后添加)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末答捕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屑那,更是在濱河造成了極大的恐慌拱镐,老刑警劉巖艘款,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沃琅,居然都是意外死亡哗咆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)益眉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晌柬,“玉大人,你說(shuō)我怎么就攤上這事郭脂∧甑猓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵展鸡,是天一觀(guān)的道長(zhǎng)屿衅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)莹弊,這世上最難降的妖魔是什么涤久? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮忍弛,結(jié)果婚禮上响迂,老公的妹妹穿的比我還像新娘。我一直安慰自己细疚,他們只是感情好蔗彤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著疯兼,像睡著了一般然遏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镇防,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音潮饱,去河邊找鬼来氧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛香拉,可吹牛的內(nèi)容都是我干的啦扬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼凫碌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼扑毡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起盛险,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瞄摊,失蹤者是張志新(化名)和其女友劉穎勋又,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體换帜,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡楔壤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惯驼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹲嚣。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖祟牲,靈堂內(nèi)的尸體忽然破棺而出隙畜,到底是詐尸還是另有隱情,我是刑警寧澤说贝,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布议惰,位于F島的核電站,受9級(jí)特大地震影響狂丝,放射性物質(zhì)發(fā)生泄漏换淆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一几颜、第九天 我趴在偏房一處隱蔽的房頂上張望倍试。 院中可真熱鬧,春花似錦蛋哭、人聲如沸县习。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)躁愿。三九已至,卻和暖如春沪蓬,著一層夾襖步出監(jiān)牢的瞬間彤钟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工跷叉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逸雹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓云挟,卻偏偏與公主長(zhǎng)得像梆砸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子园欣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容