Question

I would like to automate the upload of a file to a website using PyQt4's QWebView, but there's a part I can't figure out yet. To upload the file, the website has a button, which opens a dialog from which you are supposed to select the local file. So, these are my questions :) Is there a way to control that dialog once I click the button? Is there a better way to achieve this?

edit

The website is https://maps.google.com/ and I'm uploading a .kml file through My Places > Create Map > Import.

Was it helpful?

Solution

It is possible what you're looking for is QWebPage::chooseFile() (I suppose it depends also on how the website is handling that). Reimplement that and see if it is sufficient. Do whatever you want and return the chosen file path.

EDIT: Now that you provided the link I tested and seems to work.

OTHER TIPS

Ok, to begin let me start with background information and references.

The module that I will be using is pywin32 download here, specifically the win32gui, API reference here.

Now before you can manipulate the dialog you have to "navigate" to the window handle, the following uses win32.FindWindow API Reference here, which looks like this, where the two inputs are the lpclassName in this case #32770 (stands for a dialog) reference here and the lpWindowName which in this case is File Upload,

HWND WINAPI FindWindow(
  _In_opt_  LPCTSTR lpClassName,
  _In_opt_  LPCTSTR lpWindowName
); 

Code to locate file handle:

import win32gui

control = win32gui.FindWindow("#32770", "File Upload")

And it stores the handle, which in my case was 721470.

The next step is locate the handles of the GUI objects in the dialog, i will show an example of the Cancel button. To find the handle, I wil be using FindWindowEx API reference here,

import win32con
import win32api

ButtonHandle = win32gui.FindWindowEx(control, 0, "Button", "Cancel");
win32api.SendMessage(ButtonHandle, win32con.BM_CLICK, 0, 0)

Reference here for the BM_CLICK and here for the SendMessage.

Final code:

import win32gui
import win32api
import win32con

window = win32gui.GetForegroundWindow()
title = win32gui.GetWindowText(window)
control = win32gui.FindWindow("#32770", "File Upload")
ButtonHandle = win32gui.FindWindowEx(control, 0, "Button", "Cancel")
win32api.SendMessage(ButtonHandle, win32con.BM_CLICK, 0, 0)

Another way is to use the watsup.winGuiAuto module, here, example below:

from watsup.winGuiAuto import *

optDialog = findTopWindow(wantedText="File Upload")

CancelButton = findControl(optDialog,wantedClass="Button", wantedText="Cancel")

clickButton(SaveButton)

But i believe the easiest way is to use autoit here, i have used it before in pyqt, to shoot out commands.

Hope this helps!

Additional References (pywin32 versions):

win32gui here

win32api here

Here's a pure PyQt4 demo that more or less reproduces the default implementation:

import sys
from PyQt4 import QtCore, QtGui, QtWebKit

class WebPage(QtWebKit.QWebPage):
    def chooseFile(self, frame=None, path=''):
        return QtGui.QFileDialog.getOpenFileName(self.parent(), '', path)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    view = QtWebKit.QWebView()
    view.setPage(WebPage(view))
    view.load(QtCore.QUrl('https://maps.google.com/'))
    view.show()
    sys.exit(app.exec_())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top