【python+selenium的web自動化】- 針對上傳操作的實現方案

miki_peng發表於2021-03-15

如果想從頭學起selenium,可以去看看這個系列的文章哦!

https://www.cnblogs.com/miki-peng/category/1942527.html

關於上傳操作

​ 上傳有兩種情況:

  • ? 如果是input可以直接輸入路徑的,那麼直接使用send_keys(檔案路徑)輸入路徑即可;
  • ? 非input標籤的上傳,則需要藉助第三方工具:第三方庫 pywin32、第三方工具pyautogui等等。

​ 那這裡針對以上兩種情況分別介紹一下具體的解決方法。

input標籤

​ 定位到元素,然後直接使用send_keys(檔案路徑)輸入路徑,比較簡單。

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://xxxx")
driver.maximize_window()

# 定位上傳檔案元素
input_file = driver.find_element_by_id("xxx")

# 上傳檔案
input_file.send_keys(r"D:\learn\xx.txt")

第三方庫 pywin32

​ 非input標籤的上傳,則需要藉助第三方工具。pywin32就是這樣的一個第三方庫,主要是方便python開發者快速呼叫windows API的一個模組庫,可以識別上傳對話方塊控制程式碼進而操作。安裝命令:pip install pywin32

​ 從上面的上傳視窗,及WinSpy工具視窗,可以得出控制關係圖如下:

​ 從上圖可以看出:

  • 檔名輸入框的路徑為:上傳視窗 - > comboBoxEx32 - >comboBox - > Edit,在第四級edit;
  • 按鈕的路徑為:上傳視窗 - > button(開啟按鈕),在第二級。

​ 我們需要一步一步定位,從第一層開始往下去找,找到對應的視窗然後進行操作,步驟說明如下?:

​ 1️⃣ 第一步:先定位到第一層大視窗(即整個上傳視窗),使用win32gui模組下的FindWindow(),它是專門用於查詢大視窗的;

​ 2️⃣ 第二步:在大視窗下查詢子視窗,使用win32gui模組下的FindWindowEx(),查詢大視窗以下的子視窗都是用這個方法;

​ 3️⃣ 第三步:定位到最後要操作的視窗後,就開始要執行編輯、點選這個操作了,不管是編輯還是點選都是使用win32gui模組下的SendMessage()

​ 以上三步的相關函式說明如下?:

  • win32gui.FindWindow(IpClassName,IpWindowName):自頂層視窗開始尋找匹配條件的視窗,並返回這個視窗的控制程式碼
    • IpClassName:類名,在Spy++裡能夠看到
    • IpWindowName:視窗名,標題欄上能看到的名字
  • win32gui.FindWindowEx(hwndParent=0,hwndChildAfter=O,IpClassName=None,IpWindowName=None):搜尋類名和窗體名匹配的窗體,並返回這個窗體的控制程式碼,找不到就返回0
    • hwndParent:若不為0,則搜尋控制程式碼為hwndParent窗體的子窗體
    • hwndChildAfter:若不為0,則按照z-index的順序從hwndChildAfter向後開始搜尋子窗體,否則從第一個子窗體開始搜尋
    • IpClassName:字元型,是窗體的類名,這個可以在Spy++裡能夠看到
    • IpWindowName:字元型,是視窗名,就是標題欄上能看到的名字
  • win32gui.SendMessage(hWnd, Msg, wParam, IParam)
    • hWnd:整型,接收訊息的窗體控制程式碼
    • Msg:整型,要傳送的訊息,這些訊息都是windows預先定義好的
    • wParam:整型,訊息的wParam引數
    • IParam:整型,訊息的IParam引數

​ 以下是封裝好的上傳函式,因為window的上傳視窗是固定不變的,我們只需要封裝好一個類知道如何去呼叫即可,不需要理解它的處理細節,但如果你有興趣可以深入瞭解一下。

import win32gui
import win32con

# edit - combobox - comboBoxEx32 - #32770  編輯框在第四級
# button - #32770  開啟按鈕在第二級

# 前提:window上傳視窗已經出現,最好sleep 1-2秒等待視窗出現

def upload(filepath, browser_type="chrome"):
    if browser_type == "chrome":
        title = "開啟"
    else:
        title = ""

    # 找元素
    # 從一級開始找,一級視窗“#32770”,“開啟”
    dialog = win32gui.FindWindow("#32770", title)  # FindWindow用於找大視窗

    # 二級之後都用FindWindowEx,需要四個引數,
    # 1、元素的父親,2、從第一個子代開始找元素,3、元素的型別名(class),4、元素的文字值
    comboBoxEx32 = win32gui.FindWindowEx(dialog, 0, "ComboBoxEx32", None)  # 二級
    comBox = win32gui.FindWindowEx(comboBoxEx32, 0, "ComboBox", None)  # 三級
    # 編輯框
    edit = win32gui.FindWindowEx(comBox, 0, 'Edit', None)  # 四級
    # 開啟按鈕
    button = win32gui.FindWindowEx(dialog, 0, 'Button', '開啟(&0)')  # 二級

    # 往編輯框輸入檔案路徑
    win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, filepath)  # 傳送檔案路徑
    win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 點選開啟按鈕


if __name__ == '__main__':
    upload('D:\\test.txt')

第三方工具pyautogui

​ 還有一種更方便的方法,就是藉助第三方工具pyautoguipyautogui是一個純Python的GUI自動化工具,其目的是可以用程式自動控制滑鼠和鍵盤操作,並且支援多平臺(Windows,OS X,Linux)。強烈推薦!

​ 下面以舉例的html為例,需要先把該程式碼儲存成html檔案,後續直接訪問這個本地html檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1> hello world </h1>
<input type="file" name="mfile">
</body>
</html>

​ 安裝模組: pip install pyautogui,操作只需要兩步:

  • ? 第一步:將要上傳的檔案路徑寫入到檔名的輸入框內;
  • ? 第二步:敲回車,相當於點選【開啟】按鈕,注意回車presses要2次才能生效。
import os
import time
import pyautogui as ui
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(20)      # 隱式等待
dir = os.getcwd()
html_dir = os.path.join(dir, 'demo.html')
driver.get(html_dir)

file_elem = driver.find_element_by_name('mfile')
file_elem.click()

# 系統之間要等待
time.sleep(1)

file_dir = os.path.join(dir, 'test.txt')	# 要上傳的檔案路徑
# 寫入檔案
ui.write(file_dir)	# 直接呼叫寫入
time.sleep(0.5)
# 輸入Enter鍵, presses表示按的次數,按一次不會生效,有可能是執行太快,建議presses=2
ui.press('enter', presses=2)
time.sleep(2)

driver.quit()

​ 不管是使用哪種上傳方式,只要是作業系統的上傳視窗,操作之前記得先等待一下。

相關文章