In Python selenium implements file upload and summarizes all methods

  • 2020-05-27 06:24:41
  • OfStack

File upload is a headache that all UI automated tests have to face. Today, the blogger here shares his experience in handling file upload with you, hoping to help the majority of seleniumer which is blocked by file upload.

First of all, we need to distinguish the types of upload buttons, which can be divided into two types. One is the input box, and the other one is more complex, which is realized by js, flash, etc., and the label is not input

We analyzed the two types respectively:

1. input label

As we all know, the input tag can be send_keys directly, and this is no exception. Let's take a look at the code example:

Code:


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

driver = 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_keys
print upload.get_attribute('value') # check value

driver.quit()

Results:

baidu.py

Obviously, for input uploadings, send_keys directly is the easiest solution.

2. Non-input uploads

Next, the difficulty will be upgraded. What about those uploads that are not implemented in the input box? This kind of uploads is very strange, such as those with the a tag, div, button and object.

The problem comes again, OS bullet frame involves a level that selenium can no longer solve, how to do? It's very simple, using the OS level of operations to deal with bai, here we basically found the solution to the problem.

In general, there are several solutions:

autoIT, we call the generated au3 or exe file with the help of external force. Python pywin32 library, identify the dialog box handle, then operate SendKeys library keybd_event, similar to 3, but an analog button, ctrl+a, ctrl+c, ctrl+v...

At present, I only know the above four methods, if you have other methods, please leave a message to tell me, let me learn 1.

Let's look at 1 in turn:

1. autoIT

I've already talked about the autoIT upload and parameterization methods in another blog post, see selenium's autoit command-line arguments. I won't repeat it here.

2.win32gui

Without further ado, go to the code first:

Code:


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

dr = webdriver.Firefox()
dr.get('http://sahitest.com/demo/php/fileUpload.htm')
upload = dr.find_element_by_id('file')
upload.click()
time.sleep(1)

# win32gui
dialog = win32gui.FindWindow('#32770', u' File upload ') #  dialog 
ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None) 
ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None) #  The above 3 The sentence looks for the object in turn until it finds the input box Edit Handle to the object 
button = win32gui.FindWindowEx(dialog, 0, 'Button', None) #  Confirm button Button

win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, 'd:\\baidu.py') #  Enter the absolute address into the input box 
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) #  According to the button

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

Results:

baidu.py

Here you need a very important small tool: Spy++, there are a lot of baidu 1, of course you can also use autoIT's own tools, but it is not as good as this, it is recommended to go to the next one.

Also, you will need to install the pywin32 library, you can find the Python version of your library here, note that 32-bit or 64-bit 1 must correspond to the Python version you installed.

After the installation is complete, you can see the PyWin32 document [Python for Windows Documentation] in the start menu Python folder. You can find the corresponding method API from the Python for Windows Documentation].

A brief introduction of a few:

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

Start from the top window looking for a window that matches the condition and return the handle to that window. lpClassName: class name, visible in Spy++ lpWindowName: window name, the name you see in the title bar In the code example we used to find the upload window, you can use only one of them. Positioning with classname is easy to be disturbed by other things. Positioning with windowname is unstable.

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

Searches for a form whose class name matches the form name, and returns a handle to the form. If you can't find it, you return 0. hwndParent: if not 0, the search handle is a child form of the hwndParent form. hwndChildAfter: if not 0, start the search from hwndChildAfter back in the order z-index, otherwise start the search from the 1st subform. lpClassName: character type, is the class name of the form, which can be found in Spy++. lpWindowName: character type, is the window name, which is the title that you can see in the title bar. In the code example we used to layer upon layer to find the input box and find the ok button

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

hWnd: integer, form handle to receive messages Msg: integer, message to be sent, these messages are windows predefined, you can see the system definition message (System-Defined Messages) wParam: integer, the wParam parameter of the message lParam: integer, the lParam parameter of the message In the code example we used to enter the file address into the input box and click ok

As for the win32api module and other methods, I will not describe them here. Please refer to baidu or pywin32 for more information.

3.SendKeys

The first step is to install the SendKeys library, which you can do with pip


pip install SendKeys

Code example:


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

dr = webdriver.Firefox()
dr.get('http://sahitest.com/demo/php/fileUpload.htm')
upload = dr.find_element_by_id('file')
upload.click()
time.sleep(1)

# SendKeys
SendKeys.SendKeys('D:\\baidu.py') #  Send file address 
SendKeys.SendKeys("{ENTER}") #  Send the enter key 

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

Results:

baidu.py

The SendKeys library allows you to enter information directly into focus, but be careful to add a little more than 1 point of wait time before opening the window. Otherwise, it is easy to miss the first letter send (or you can add a useless character before the address). However, I think this method is very unstable and not recommended.

4.keybd_event

win32api provides an keybd_event() method to simulate buttons. However, this method is troublesome and unstable, so it is not recommended. Some code examples are given below.


...

#  Look for the 1 a input Box, enter the address of the file you want to upload, and cut it to the clipboard  
video.send_keys('C:\\Users\\Administrator\\Pictures\\04b20919fc78baf41fc993fd8ee2c5c9.jpg')
video.send_keys(Keys.CONTROL, 'a') # selenium the send_keys ( ctrl+a ) 
video.send_keys(Keys.CONTROL, 'x') # (ctrl+x)
driver.find_element_by_id('uploadImage').click() #  Click the upload button to open the upload box 

#  Paste ( ctrl + v ) 
win32api.keybd_event(17, 0, 0, 0) #  Press the button  ctrl
win32api.keybd_event(86, 0, 0, 0) #  Press the button  v
win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0) #  Rising button  v
win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0) #  Rising button  ctrl
time.sleep(1)

#  A carriage return ( enter ) 
win32api.keybd_event(13, 0, 0, 0) #  Press the button  enter
win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0) #  Rising button  enter

...

Well, you can even type in the entire path by pressing a button, but I don't think anyone wants to do that. And in this process you can't move the mouse at will, can't use clipboard, too unstable, so it is not recommended that you use this method.

3. Multiple file uploads

There is one more case to consider, and that is multiple file uploads. How to upload multiple files, of course we still input the file path into the input box, so the only thing 1 has to figure out is how to write the file path when uploading multiple files.

Let me tell you something. Multiple file uploads are simple things like putting a single path in quotes in the file path box and separating multiple paths with commas. For example:
"D: \ a txt" "D: \ b txt"

However, it is important to note that only multiple files in the same path can be used in this way, otherwise it will fail (the following writing method is not allowed) :
"C: \ a txt" "D: \ b txt"

Try this next example:

Code:


# -*- coding: utf-8 -*-

from selenium import webdriver
import win32gui
import win32con
import time

dr = webdriver.Firefox()
dr.get('http://www.sucaijiayuan.com/api/demo.php?url=/demo/20150128-1')

dr.switch_to.frame('iframe') # 1 Need to pay attention to frame
dr.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)

#  The code in the example above is 1 Sample, only the parameters passed in here are different, if you want to write 1 Three upload functions encapsulate the upload function 
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').text
dr.quit()

Results:

Select 3 files, 1.17KB in total.

It can be seen that the multi-file upload is not so complicated, but also very simple. The only difference of 1 is that the input parameters are different. autoIT can also be implemented, you can try it yourself if you are interested.

And we can find 1 point, is the above window code is basically the same as the previous example, that we can take the upload part out, write 1 function, so every time to upload, directly to call the function, pass in the parameters.


Related articles: