Python selenium file upload method summary

  • 2020-05-10 18:26:52
  • 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:

Sample url: http: / / www sahitest. com demo/php/fileUpload htm  

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 uploads, send_keys directly is the easiest solution.

2. Non-input uploads

The next difficulty is to upgrade, for those not input box implementation of the upload how to do, this kind of upload strange, useful a tag, useful div, useful button, useful object, we have no way to directly on the web page to deal with these uploads, only 1 way is to open OS pop-up, to deal with the pop-up.

The problem comes again, OS bullet frame involved in the level is not selenium can solve, how to do? It's very simple, using the OS level of operations to deal with it, here we basically find the solution to the problem.

In general, there are several solutions:
  1.autoIT, with the help of external force, we will call the generated au3 or exe file.
  2.Python pywin32 library, identify the dialog box handle, then operate
  3. SendKeys library
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 parameters. I won't repeat it here.

2.win32gui

Without further ado, go to the code first:

Sample url: http: / / www sahitest. com demo/php/fileUpload htm  

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 the tools that autoIT comes with, but it is not as good as this, I suggest you go to the next one.

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

When 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 Python for Windows Documentation].

A brief introduction of a few:

win32gui.FindWindow(lpClassName=None, lpWindowName=None):
  & # 8226; Start from the top window looking for a window that matches the condition and return the handle to that window.
  & # 8226; lpClassName: class name, which you can see in Spy++
  & # 8226; lpWindowName: window name, the name you see in the title bar
  & # 8226; In the code example we used to find the upload window, you can use only one of them, classname positioning is easy to be disturbed by other things, windowname positioning is not stable, different upload dialog box may be window_name different, how to locate depends on your situation.  

win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None)
  & # 8226; 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.
  & # 8226; hwndParent: if it is not 0, the search handle is a child of the hwndParent form.
  & # 8226; hwndChildAfter: if it is not 0, search the child form from hwndChildAfter back in order z-index, or from the first child form.
  & # 8226; lpClassName: character type, is the class name of the form, which can be found in Spy++.
  & # 8226; lpWindowName: character type, is the window name, which is the title that you can see in the title bar.
  & # 8226; 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)
  & # 8226; hWnd: integer, form handle to receive messages
  & # 8226; Msg: integer, message to be sent. These messages are predefined by windows. See system definition message (System-Defined Messages).
  & # 8226; wParam: integer, the wParam parameter of the message
  & # 8226; lParam: integer, the lParam parameter of the message
  & # 8226; In the code example we used to enter the file address into the input box and hit the ok button  

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 install using pip

pip install SendKeys  

Code example:

Sample url: http: / / www sahitest. com demo/php/fileUpload htm  

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)

# 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 keys, but this method is troublesome and unstable, so it is not recommended. The following is part of the code examples, if you want to study, go to baidu to learn.


#  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:

Sample url: http: / / www sucaijiayuan. com/api/demo php & # 63;   url = / demo / 20150128-1

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 for a total of 1.17KB.

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.

Look, uploads are easy to handle.


Related articles: