丁燁敏
(湖南工業(yè)職業(yè)技術(shù)學(xué)院電氣工程學(xué)院,長沙 410208)
學(xué)生的畢業(yè)設(shè)計(jì)成果的管理是一項(xiàng)繁瑣的工作,其中就包含畢業(yè)設(shè)計(jì)成果的保存。目前大部分高校都要求學(xué)生將畢業(yè)設(shè)計(jì)成果提交保存到指定的管理平臺。提交上傳畢業(yè)設(shè)計(jì)成果的工作,可能由學(xué)生自己,或者畢業(yè)設(shè)計(jì)指導(dǎo)老師完成,而且基本上都是通過手動(dòng)完成。只要是人為的操作,就會(huì)出現(xiàn)問題。為了節(jié)省時(shí)間,提高畢業(yè)設(shè)計(jì)成果管理工作的效率,使用應(yīng)用程序?qū)崿F(xiàn)畢業(yè)設(shè)計(jì)成果自動(dòng)上傳提交非常有必要。
學(xué)生畢業(yè)設(shè)計(jì)成果管理平臺一般都是通過Web進(jìn)行交互操作。因?yàn)楣芾砥脚_的API不一定開放給一般用戶使用。所以,要實(shí)現(xiàn)自動(dòng)上傳功能,必須考慮到和畢業(yè)設(shè)計(jì)成果管理平臺Web界面的交互操作。
目前能夠?qū)崿F(xiàn)與Web界面自動(dòng)交互的工具有Selenium[1]、QTP[2]、Watir[3]、Robot Framework[4]等。QTP是商業(yè)版本不免費(fèi),使用成本太高。Watir使用Ruby語言進(jìn)行腳本開發(fā),對于沒有學(xué)過Ruby的用戶而言可能存在一些困難。Robot Framework功能很強(qiáng)大,但是更適用于進(jìn)行自動(dòng)化測試。Selenium是一個(gè)強(qiáng)大的Web自動(dòng)化工具,使用靈活并且支持各種語言、多種操作系統(tǒng)和瀏覽器,并且是開源的。綜合考慮,確定使用Selenium實(shí)現(xiàn)Web自動(dòng)交互。
登錄管理平臺需要獲取學(xué)生的相關(guān)信息,例如學(xué)生的賬戶、密碼、班級學(xué)號、課題名稱等,這些數(shù)據(jù)可能保存在excel表格中。因此,讀取excel文件數(shù)據(jù)也成為畢業(yè)設(shè)計(jì)成果上傳提交的前提。Python提供了強(qiáng)大的文件讀取和數(shù)據(jù)處理功能,并且也提供了Selenium程序包。因此最終確認(rèn)使用Python+Selenium的開發(fā)技術(shù)來實(shí)現(xiàn)畢業(yè)設(shè)計(jì)成果自動(dòng)上傳功能。
開發(fā)環(huán)境方面,操作系統(tǒng)使用的是Windows 10。Python選用的版本是3.7.3。Python環(huán)境安裝完成后,使用pip install selenium命令在線安裝selenium最新版本,安裝成功后可以使用pip show selenium命令查看安裝的selenium版本。集成開發(fā)環(huán)境使用PyCharm。
學(xué)生畢業(yè)設(shè)計(jì)成果自動(dòng)提交需要實(shí)現(xiàn)如下需求:
(1)自動(dòng)讀取本地excel文件中保存的學(xué)生畢業(yè)設(shè)計(jì)相關(guān)信息,包括學(xué)生姓名、班級學(xué)號、畢業(yè)設(shè)計(jì)課題名稱、管理平臺用戶名、管理平臺密碼等。
(2)自動(dòng)打開管理平臺網(wǎng)頁,使用用戶名和密碼自動(dòng)進(jìn)行登錄。
(3)自動(dòng)在管理平臺新建畢業(yè)設(shè)計(jì)課題任務(wù)。
(4)自動(dòng)提交畢業(yè)設(shè)計(jì)成果并保存。
(5)自動(dòng)獲取畢業(yè)設(shè)計(jì)成果上傳后的鏈接網(wǎng)址,并保存到本地excel文件中。
通過上面功能描述,可以將程序分為兩大功能模塊:excel文件處理和Web自動(dòng)交互。excel文件處理功能模塊主要使用pandas程序包實(shí)現(xiàn),可以使用pip install pandas安裝pandas。使用pandas讀寫excel文件的內(nèi)容不做詳細(xì)描述,在這里主要介紹使用Selenium如何實(shí)現(xiàn)自動(dòng)和Web進(jìn)行交互。
實(shí)現(xiàn)和Web自動(dòng)交互,就需要打開Web界面,找到Web界面上的元素,模擬人為操作,例如鍵盤輸入、鼠標(biāo)點(diǎn)擊、文件選擇等功能。
Selenium支持多種瀏覽器,本程序使用的是谷歌瀏覽器。在配置完瀏覽器后,需要使用Selenium WebDriver加載要打開管理平臺Web對應(yīng)的鏈接地址(URL)。示例代碼如下:
from selenium import webdriver
driver=webdriver.Chrome()
driver.get(URL)
Selenium提供了多種查找Web頁面節(jié)點(diǎn)元素的 方 法[5],具 體包 括:find_element_by_id、find_element_by_name、find_element_by_xpath、find_element_by_link_text、find_element_by_partial_link_text、find_element_by_tag_name、find_element_by_class_name、find_element_by_css_selector。需要注意的是,這些方法的返回值是list列表類型(結(jié)果保存在list列表中)。查找Web頁面元素的示例如下。
使用手機(jī)號作為登錄名進(jìn)行登錄時(shí),輸入手機(jī)號碼的編輯框HTML描述如下:
<input type="text"class="ipt-tel"placeholder="手機(jī)號"id="phone"maxlength="50">
可以使用element=driver.find_elements_by_id("phone")查找到界面上的該編輯框。返回值element表示查找結(jié)果對應(yīng)的list列表。
登錄按鈕的HTML描述如下:
<input type="button"value="登錄"class="loginSub"onclick="goPassport2Login();">
可以使用element=driver.find_elements_by_class_name("loginSub")查找到界面上的該登錄按鈕。
當(dāng)頁面的元素既沒有id屬性也沒有name屬性時(shí),可以使用xpath來查找該元素。xpath表示xml元素的路徑,它完全可以替代其他元素(id、name、class_name、tag_name等)定位方式。其HTML描述如下:
<html>
<body>
<form id="inputForm"name="inputForm">
<input type="text"name="subject"id="subject"value=""placeholder="輸入專題名稱">
<input type="text"name="author"id="author"value=""placeholder="輸入作者名">
</form>
</body>
<html>
查找form表單元素,可以使用如下方法:element=driver.find_elements_by_xpath("/html/body/form")。該種方法使用form表單元素在HTML文件中完整路徑位置來進(jìn)行定位查找。
當(dāng)然也可以使用element=driver.find_elements_by_xpath("http://*[@id=’inputForm’]")。該種方法是通過相對定位來查找,//表示從匹配選擇的當(dāng)前節(jié)點(diǎn)下繼續(xù)查找;*通配符,表示任意元素節(jié)點(diǎn)。整個(gè)語句表示HTML文件當(dāng)前位置的任意元素節(jié)點(diǎn)下id名為inputForm的元素。
除了使用*通配符,在xpath中還可以使用文本定位、模糊定位等。例如element=driver.find_elements_by_xpath("http://*//input[starts-with(@id,'sub')]"),表示在HTML文件當(dāng)前位置的任意元素節(jié)點(diǎn)下找到id名以sub開頭的節(jié)點(diǎn)元素。
找到頁面節(jié)點(diǎn)元素后,需要模擬用戶的操作。例如鍵盤輸入數(shù)據(jù)、點(diǎn)擊等。上文使用element=driver.find_elements_by_id("phone")找到輸入手機(jī)號碼的編輯框,可以使用element[0].send_keys(phoneNumber)模擬用戶在該編輯框中輸入手機(jī)號碼。注意這里使用的是element[0],因?yàn)閒ind_element_by_id的返回結(jié)果是list列表,需要指定取出該列表中指定位置的元素。
同樣,上文使用element=driver.find_elements_by_class_name("loginSub")找到界面上的登錄按鈕后,可以使用element[0].click(),或者element[0].send_keys(Keys.ENTER),模擬用戶點(diǎn)擊該按鈕。其中Keys.ENTER表示回車鍵。
當(dāng)Web界面進(jìn)行跳轉(zhuǎn)打開新的Web界面時(shí),Selenium需要切換窗口才能在新的Web頁面進(jìn)行元素節(jié)點(diǎn)查找[6]。具體如下:
driver.switch_to.window(driver.window_handles[-1])
語句中window_handles表示W(wǎng)eb窗口界面句柄列表,-1表示切換到最后一個(gè)界面,也就是最新打開的界面。如果目前已經(jīng)打開了三個(gè)Web窗口界面,上面的語句中將-1改為-2,即可跳轉(zhuǎn)到第二個(gè)Web窗口界面進(jìn)行操作。也可以通過first_win=driver.current_window_handle獲取當(dāng)前Web窗口界面的handle句柄。后續(xù)如果需要切換回該Web窗口界面時(shí),執(zhí)行driver.switch_to.window(first_win)即可。
當(dāng)然,HTML中也有iframe標(biāo)簽,表示內(nèi)聯(lián)框架,可以理解為在一個(gè)HTML中內(nèi)嵌一個(gè)子HTML。Selenium不能直接在父HTML中查找到iframe中定義的元素節(jié)點(diǎn),也需要先進(jìn)行切換[7],具體方法如下:
driver.switch_to.frame(frame_name)
其中,frame_name表示iframe的名稱。執(zhí)行上述語句后即可跳轉(zhuǎn)到iframe中操作節(jié)點(diǎn)元素。當(dāng)iframe中操作結(jié)束,需要返回到之前的Web窗口界面時(shí),需要執(zhí)行如下語句。
driver.switch_to.default_content()
當(dāng)在Web界面中點(diǎn)擊文件上傳時(shí),首先需要用戶選擇本地文件。Python中如何實(shí)現(xiàn)自動(dòng)選擇本地文件呢?此時(shí)需要借助pywin32程序包。pywin32程序包包含了Windows系統(tǒng)的Win32 API,能創(chuàng)建和使用COM對象和圖形窗口界面??梢允褂胮ip install pywin32命令進(jìn)行安裝。
在使用Selenium Webdriver打開Windows文件選擇窗口后,調(diào)用函數(shù)win32_select_file()可以實(shí)現(xiàn)Windows本地文件選擇。
import win32gui
import win32con
def win32_select_file(path):
dialog=win32gui.FindWindow("#32770","打開")#"#32770"表示彈出框的窗口類名
comboBoxEX32=win32gui.FindWindowEx(dialog,0,"ComboBoxEx32",None)
comboBox=win32gui.FindWindowEx(comboBox-EX32,0,"ComboBox",None)
editBox=win32gui.FindWindowEx(comboBox,0,"Edit",None)
button=win32gui.FindWindowEx(dialog,0,"Button","打開(&0)")
win32gui.SendMessage(editBox,win32con.WM_SETTEXT,None,path)
win32gui.SendMessage(dialog,win32con.WM_COMMAND,1,button)
其中win32_select_file()的參數(shù)path表示要上傳的本地文件的完整路徑。執(zhí)行win32_select_file()函數(shù)后,即設(shè)置了需要上傳的文件,接下來依舊使用Selenium模擬人為操作,例如鼠標(biāo)點(diǎn)擊等,觸發(fā)文件上傳。
所有上傳文件操作、保存操作結(jié)束后,需要保存畢業(yè)設(shè)計(jì)成果上傳保存后的Web頁面鏈接。在Selenium中可以使用如下語句獲取當(dāng)前Web頁面鏈接地址。
retUrl=driver.current_url
retUrl即保存當(dāng)前Web頁面的鏈接地址。如果畢業(yè)設(shè)計(jì)成果上傳后保存的Web頁面鏈接地址并非當(dāng)前Web界面的鏈接地址,那么可以結(jié)合Selenium切換窗口的操作,最終獲取到畢業(yè)設(shè)計(jì)成果上傳后保存的Web頁面鏈接地址。
本文使用Python+Selenium,實(shí)現(xiàn)對高校學(xué)生的畢業(yè)設(shè)計(jì)成果自動(dòng)提交保存到管理平臺功能,測試結(jié)果表明,Python+Selenium實(shí)現(xiàn)的程序代碼簡潔凝練,通俗易懂,便于維護(hù),可以大大減少學(xué)生、老師重復(fù)性的繁瑣工作,并且能夠保證提交的質(zhì)量。對于有類似需求的工作場景,也具有非常高的參考價(jià)值。