启动 google chrome 并通过 pywinauto 输入网址的最佳方式是什么

what is the best way to start google chrome and input a web address by pywinauto

我从博客(http://technapstar.blogspot.fi/2014/07/automation-with-pywinauto.html)学习了如何启动google chrome 并通过pywinauto输入网址如下:

Python 3.6.1rc1 (v3.6.1rc1^0:e0fbe5feee4f9c00f09eb9659c2182183036261a, Mar  4 2017, 20:00:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import pywinauto
>>> pywinauto.__version__
'0.6.2'
>>> from pywinauto.application import Application
>>> app = Application().start("chrome.exe")

Warning (from warnings module):
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 982
    UserWarning)
UserWarning: 32-bit application should be automated using 32-bit Python (you     use 64-bit Python)
>>> app.window_(title='New Tab')
<pywinauto.application.WindowSpecification object at 0x0000000002FFABE0>
>>> app.window_().TypeKeys('{F6}')
<pywinauto.controls.hwndwrapper.DialogWrapper object at 0x0000000004258320>
>>> app.window_().TypeKeys('{ESC}')
<pywinauto.controls.hwndwrapper.DialogWrapper object at 0x0000000004243518>
>>> app.window_().TypeKeys('www.google.com')
<pywinauto.controls.hwndwrapper.DialogWrapper object at 0x0000000004225D68>
>>> app.window_().TypeKeys('{ENTER}')
<pywinauto.controls.hwndwrapper.DialogWrapper object at 0x00000000042436D8>
>>> 

但是,当我尝试以同样的方式启动另一个google chrome window时,我遇到了以下错误。

>>> app1 = Application().start("chrome.exe")

Warning (from warnings module):
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 982
    UserWarning)
UserWarning: 32-bit application should be automated using 32-bit Python (you use 64-bit Python)
>>> app1.window_(title='New Tab')
<pywinauto.application.WindowSpecification object at 0x0000000004243470>
>>> app1.window_().TypeKeys('{F6}')
Traceback (most recent call last):
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 243, in __resolve_control
    criteria)
  File "D:\Python\lib\site-packages\pywinauto\timings.py", line 424, in wait_until_passes
    raise err
pywinauto.timings.TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    app1.window_().TypeKeys('{F6}')
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 365, in __getattribute__
    ctrls = self.__resolve_control(self.criteria)
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 246, in __resolve_control
    raise e.original_exception
  File "D:\Python\lib\site-packages\pywinauto\timings.py", line 402, in wait_until_passes
    func_val = func(*args)
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 188, in __get_ctrl
    dialog = self.backend.generic_wrapper_class(findwindows.find_element(**criteria[0]))

我google查了一下,但没找到答案。有人可以建议用 pywinauto 操作 google chrome 的最佳方法是什么吗?或 pywinauto 目前不是操作 google chrome 的合适工具。

[编辑] 按照 Vasily 的学生示例代码仍然无法正常工作,请参见此处:

>>> app = Application(backend='uia');
>>> app.start('chrome.exe --force-renderer-accessibility')
<pywinauto.application.Application object at 0x00000000045D80B8>
>>> app.window().type_keys('{F6}')
<pywinauto.controls.uiawrapper.UIAWrapper object at 0x00000000045D8AC8>

到目前为止一切正常,但是当我尝试使用另一个 chrome 浏览器时,我遇到了以下错误:

>>> app1 = Application(backend='uia');
>>> app1.start('chrome.exe --force-renderer-accessibility')
<pywinauto.application.Application object at 0x0000000003324F28>
>>> app1.window().type_keys('{F6}')
Traceback (most recent call last):
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 243, in __resolve_control
    criteria)
  File "D:\Python\lib\site-packages\pywinauto\timings.py", line 424, in wait_until_passes
    raise err
pywinauto.timings.TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    app1.window().type_keys('{F6}')
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 365, in __getattribute__
    ctrls = self.__resolve_control(self.criteria)
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 246, in __resolve_control
    raise e.original_exception
  File "D:\Python\lib\site-packages\pywinauto\timings.py", line 402, in wait_until_passes
    func_val = func(*args)
  File "D:\Python\lib\site-packages\pywinauto\application.py", line 188, in __get_ctrl
    dialog = self.backend.generic_wrapper_class(findwindows.find_element(**criteria[0]))
  File "D:\Python\lib\site-packages\pywinauto\findwindows.py", line 87, in find_element
    raise ElementNotFoundError(kwargs)
pywinauto.findwindows.ElementNotFoundError: {'backend': 'uia', 'process': 2832}
>>> 

首先,您需要 运行 Chrome 为所有页面启用辅助功能(这里有一些 tips and tricks on that):

app = Application().start('chrome.exe --force-renderer-accessibility')

第二个 Chrome 使用 backend='uia'(MS UI 自动化技术)可以更容易地实现自动化,您需要明确指定它。有关后端和 pywinauto 基础知识的更多详细信息可以在 Getting Started Guide 中找到(真的建议大家阅读)。它还解释了在哪里可以找到 Inspect.exe 来浏览 UI 元素层次结构等等。举个小例子:

app = Application(backend='uia').start('chrome.exe --force-renderer-accessibility')

第三个 Chrome 可能会在不同的进程中启动新标签页。因此,您需要使用 titletitle_re 标准连接到这个新进程。

app_new_tab = Application(backend='uia').connect(path='chrome.exe', title_re='New Tab')

另一种方法是使用 Desktop 对象(进程不可知方式):

NewTab = Desktop(backend='uia').NewTab
NewTab.print_control_identifiers() # prints UI elements subtree

[编辑] 我的学生编写了一个示例脚本,将 zip 文件从 explorer.exe 拖动到 Google 在隐身模式下使用 Chrome 驱动器:test_explorer_google_drive.py。已在英文版上测试。

# encoding: utf-8
from __future__ import print_function
from os import path
from pywinauto import Desktop, Application

chrome_dir = r'"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"'
tab_log_in = u'Meet Google Drive - One place for all your files (Incognito)'
tab_drive = 'My Drive - Google Drive (Incognito)'

# # start google chrome
chrome = Application(backend='uia')
chrome.start(chrome_dir + ' --force-renderer-accessibility --incognito --start-maximized '
             'https://accounts.google.com/ServiceLogin?service=wise&passive=1209600&continue=https:'
             '//drive.google.com/?urp%3Dhttps://www.google.ru/_/chrome/newtab?espv%253D2%2526ie%253DUT%23&followup='
             'https://drive.google.com/?urp%3Dhttps://www.google.ru/_/chrome/newtab?espv%253D2%2526ie%253DUT'
             '&ltmpl=drive&emr=1#identifier')

# wait while a page is loading
chrome[tab_log_in].child_window(title_re='Reload.*', control_type='Button').wait('visible', timeout=10)
ch_window = chrome[tab_drive].child_window(title="Google Chrome", control_type="Custom")

# log in
chrome.window().type_keys('TestPywinauto{ENTER}')  # username
chrome[tab_log_in].child_window(title="Google Chrome", control_type="Custom").\
    child_window(title="Back", control_type="Image").wait(wait_for='visible', timeout=10)

chrome.window().type_keys('testpywinauto123{ENTER}')  # password
ch_window.child_window(title="Getting started PDF", control_type="ListItem").wait(wait_for='visible')

# start explorer in the current path
dir_path = path.join(path.dirname(path.realpath(__file__)), 'UIA_Drive')
explorer = Application().start('explorer.exe ' + dir_path)
Desktop(backend='uia').window(title='UIA_Drive', active_only=True).wait('visible', timeout=10)
dlg = Application(backend='uia').connect(path='explorer.exe', title='UIA_Drive')

# find file
file = dlg.UIA_Drive.ItemsView.wrapper_object().get_item('test.zip')

# drag n drop
destination = chrome.top_window().wrapper_object()
file.press_mouse_input(coords=file.rectangle().mid_point())
file.move_mouse_input(coords=destination.rectangle().mid_point())
chrome.top_window().set_focus()
file.release_mouse_input(coords=destination.rectangle().mid_point())

# wait upload file
ch_window.child_window(title="test.zip Compressed Archive", control_type="ListItem").wait('visible')

print('DONE')

更简单的开始方式是:

from pywinauto.application import Application
chrome_dir = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
start_args = ' --force-renderer-accessibility --start-maximized https://www.google.com/'
app = Application(backend="uia").start(chrome_dir+start_args)