1. 程式人生 > >Selenium+Python:下載檔案(Firefox 和 Chrome)

Selenium+Python:下載檔案(Firefox 和 Chrome)

1.      環境

作業系統

Win10

IDE

Eclipse (Oxygen 4.7)+ PyDev 5.9.2 (JDK1.8)

Python

3.5

Selenium

selenium-3.9.0-py2.py3-none-any.whl

FirefoxDriver

0.20.0

Firefox瀏覽器

59.0.2(32位)

ChromeDriver

2.34

Chrome瀏覽器

63.0.3239.84

2.      Firefox

    這是蟲師書裡面的一個例子,我直接copy下來了

from selenium import webdriver

fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.manager.showWhenStarting", False) # 不起作用
fp.set_preference("browser.download.dir", os.getcwd())
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream")

driver = webdriver.Firefox(firefox_profile=fp)
driver.get("http://pypi.Python.org/pypi/selenium")
driver.find_element_by_partial_link_text("selenium-3.11.0-py2.py3-none-any").click()

    但是很不幸,我這兒運行了,還是會彈出確認下載對話方塊,雖然設定了browser.download.manager.showWhenStarting為Flase,而由於Selenium無法操作該對話方塊,程式就卡在那兒了沒能下載檔案。

    我發現確認下載對話方塊,預設的焦點就在【確定】上,就試著在程式碼的最後新增這樣一句:

ActionChains(driver).key_down(Keys.ENTER).perform()

當這個對話框出現的時候,手動鍵入ENTER是可以下載的,但這句程式碼並沒有起作用,仍然沒有下載檔案。

3.      Chrome

    又試著增加了一些等待時間,始終沒成功,就想著先換一個瀏覽器試試吧。

options = webdriver.ChromeOptions()
prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': os.getcwd()}
options.add_experimental_option('prefs', prefs)

driver = webdriver.Chrome(chrome_options=options)
driver.get("http://pypi.Python.org/pypi/selenium")driver.find_element_by_partial_link_text("selenium-3.11.0-py2.py3-none-any").click()

    對Chrome瀏覽器設定了profile.default_content_settings.popups為0是起作用的,執行這段程式碼,並沒有彈出確認提示框,檔案可以下載下來。

4.      Firefox+Pywin32

總覺得Firefox應該也會有辦法來操作那個確認下載對話方塊,百度了一下,有提到Pywin32,可以獲取並操作Windows視窗。那就先安裝一個吧。 

    Pywin32,我是直接在命令列切換到Python根目錄\Scripts下,用pip install pywn32來安裝的:

                          

     此外還用到一個可以獲取Windows視窗屬性的小工具Sky++,下載瞭解壓縮就可以用了。執行Sky++後,點選【搜尋】-【視窗搜尋】選單項開啟【視窗搜尋】對話方塊

                                            

按住其中的查詢程式工具拖動到確認下載對話方塊後釋放,【視窗搜尋】對話方塊中會顯示該視窗的控制代碼、標題、類等屬性

                                            

通過後兩個屬性,就可以呼叫win32gui.FindWindow()獲取該視窗的控制代碼,進而試著操作該視窗。注意 :雖然在Sky++中已經得到了控制代碼,但程式中不能直接用,因為每次執行視窗控制代碼是不同的。

     於是我在之前的程式碼後面增加了下面這句程式碼

dialog = win32gui.FindWindow("MozillaDialogClass", u"正在開啟 selenium-3.11.0-py2.py3-none-any.whl")

列印了一下dialog,是有值的,就說明成功地獲取到了視窗控制代碼了。 

    在獲取到對話方塊的控制代碼後,就應該進一步獲取【確定】按鈕的控制代碼,然後點選該按鈕,這樣就應該可以下載檔案了

button = win32gui.FindWindowEx(dialog,None, "Button",None)
win32gui.PostMessage(button, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, 0)
win32gui.PostMessage(button, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, 0)

可是一直沒成功,列印button一直是0,沒有能獲取到按鈕的控制代碼,我懷疑是因為類名不正確的原因,但Sky++上無法看到按鈕的資訊,將類名換了又換,或許是"MozillaButtonClass",但始終沒有獲取。

    轉而我又想,既然對話方塊獲取到了,那對對話方塊鍵入ENTER呢,或許就可以了

win32gui.SendMessage(dialog,win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)

嗯,真的可以了。因此用Firefox下載檔案的完整程式碼是

from selenium import webdriver
import win32gui, win32con

fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.dir", os.getcwd())
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream")

driver = webdriver.Firefox(firefox_profile=fp)
driver.get("http://pypi.Python.org/pypi/selenium")
driver.find_element_by_partial_link_text("selenium-3.11.0-py2.py3-none-any").click()

dialog = win32gui.FindWindow("MozillaDialogClass", u"正在開啟 selenium-3.11.0-py2.py3-none-any.whl")
win32gui.SendMessage(dialog,win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)

    只是有一個問題,在import win32gui和win32con時,會有錯誤標識

但執行沒問題,不知道為什麼。。。。。。 

    還要注意的是,需要根據當前網路的狀況,以及下載檔案的大小,適當新增一些等待時間,不然會可能出現最後關閉瀏覽器驅動時檔案還沒下完的情況。

5.      再次Firefox

    以上那些是昨天寫的,是到昨天晚上為止的認識。今兒早上來了,在搜另外一個問題的時候,發現有博文說Firefox不能下載的原因,很可能是因為"browser.helperApps.neverAsk.saveToDisk"設定的檔案型別不對的緣故,我把那個例子裡面的型別"binary/octet-stream"貼過來試了一下,果然是可以的。但關於browser.download.manager.showWhenStarting設定為Flase不彈出提示框,其實程式碼中把檔案型別設定正確了,沒有設定browser.download.manager.showWhenStarting,也並沒有彈出提示框。

from selenium import webdriver

fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.dir", os.getcwd())
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream")

driver = webdriver.Firefox(firefox_profile=fp)
driver.get("http://pypi.Python.org/pypi/selenium")
driver.find_element_by_partial_link_text("selenium-3.11.0-py2.py3-none-any").click()

    有朋友友情提示,該加個參考資料小節。以前寫東西的時候倒是每次都有注意引用這個問題,而最近寫的也只是記錄自己的一個學習Selenium+Python Web自動化測試的過程。不過好習慣還是該保持,這篇已經不太記得自己到底搜了哪些文章了,就記下幾篇還記得的吧。

6.      參考資料

[1]  《Selenium2自動化測試實戰:基於Python語言》蟲師編著 電子工業出版社 2016年1月

[2] 用selenium的webdriver下載檔案(基於python,firefox和chrome) https://blog.csdn.net/cyjs1988/article/details/74988997

[3]   Selenium 設定瀏覽器下載  http://www.cnblogs.com/fnng/p/7700620.html