Vin*_*d K 19 python active-window
我想使用python在屏幕上获取活动窗口.
例如,路由器的管理界面,您输入用户名和密码作为admin
我希望使用python捕获该管理界面以自动输入用户名和密码.
为了做到这一点,我需要进口什么?
Wil*_*ers 20
在Windows上,您可以使用python for windows扩展(http://sourceforge.net/projects/pywin32/):
from win32gui import GetWindowText, GetForegroundWindow
print GetWindowText(GetForegroundWindow())
Run Code Online (Sandbox Code Playgroud)
下面的代码是针对python 3的:
from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowText(GetForegroundWindow()))
Run Code Online (Sandbox Code Playgroud)
(在http://scott.sherrillmix.com/blog/programmer/active-window-logger/上找到)
Mit*_*ers 18
感谢 Nuno André 的回答,他展示了如何使用 ctypes 与 Windows API 交互。我已经使用他的提示编写了一个示例实现。
该ctypes库自 v2.5 起包含在 Python 中,这意味着几乎每个用户都拥有它。而且它是一种比旧的和死的库更干净的界面win32gui(在撰写本文时于 2017 年最后一次更新)。((2020 年末更新:死win32gui库已重新命名为pywin32,因此如果您想要一个维护的库,它现在又是一个有效的选择。但该库比我的代码慢 6%。))
文档在这里:https : //docs.python.org/3/library/ctypes.html(如果你想编写自己的代码,你必须阅读它的使用帮助,否则你会导致分段错误崩溃,呵呵。)
基本上,ctypes 包括最常见的 Windows DLL 的绑定。这是在纯 Python 中检索前景窗口标题的方法,无需外部库!只是内置的ctypes!:-)
ctypes 最酷的地方是你可以谷歌任何你需要的任何Windows API,如果你想使用它,你可以通过 ctypes 来做!
Python 3 代码:
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
# 1-liner alternative: return buf.value if buf.value else None
if buf.value:
return buf.value
else:
return None
Run Code Online (Sandbox Code Playgroud)
性能非常好:0.01我电脑上的 MILLISECONDS(0.00001秒)。
也可以在 Python 2 上进行非常小的更改。如果您使用的是 Python 2,我认为您只需删除类型注释(from typing import Optional和 -> Optional[str])。:-)
享受!
Win32技术说明:
该length变量是UTF-16(Windows Wide“Unicode”)字符中实际文本的长度。(它不是字节数。)我们必须添加+ 1以在 C 样式字符串的末尾为空终止符添加空间。如果我们不这样做,缓冲区中将没有足够的空间来容纳实际文本的最终真实字符,Windows 将截断返回的字符串(这样做是为了确保它适合超级重要的最终字符串 Null -终结者)。
该create_unicode_buffer函数为那么多 UTF-16 字符分配空间。
大多数(或全部?总是阅读 Microsoft 的 MSDN 文档!)与 Unicode 文本相关的 Windows API 将缓冲区长度作为字符,而不是字节。
还要仔细查看函数调用。有些以W(例如GetWindowTextLengthW)结尾。这代表“宽字符串”,它是 Unicode 字符串的 Windows 名称。执行这些W调用以获得正确的 Unicode 字符串(具有国际字符支持)非常重要。
PS:Windows 使用 Unicode 已经很长时间了。我知道 Windows 10 是完全Unicode 并且只需要W函数调用的事实。我不知道旧版本的 Windows 使用其他多字节字符串格式的确切截止日期,但我认为它是在 Windows Vista 之前,谁在乎呢?旧的 Windows 版本(甚至 7 和 8.1)已经过时并且不受 Microsoft 支持。
再次......享受!:-)
2020 年末更新,基准测试与pywin32库:
import time
import win32ui
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
return buf.value if buf.value else None
def getForegroundWindowTitle_Win32UI() -> Optional[str]:
# WARNING: This code sometimes throws an exception saying
# "win32ui.error: No window is is in the foreground."
# which is total nonsense. My function doesn't fail that way.
return win32ui.GetForegroundWindow().GetWindowText()
iterations = 1_000_000
start_time = time.time()
for x in range(iterations):
foo = getForegroundWindowTitle()
elapsed1 = time.time() - start_time
print("Elapsed 1:", elapsed1, "seconds")
start_time = time.time()
for x in range(iterations):
foo = getForegroundWindowTitle_Win32UI()
elapsed2 = time.time() - start_time
print("Elapsed 2:", elapsed2, "seconds")
win32ui_pct_slower = ((elapsed2 / elapsed1) - 1) * 100
print("Win32UI library is", win32ui_pct_slower, "percent slower.")
Run Code Online (Sandbox Code Playgroud)
在 AMD Ryzen 3900x 上多次运行后的典型结果:
我的函数:4.5769994258880615 秒
Win32UI 库:4.8619983196258545 秒
Win32UI 库慢 6.226762715455125%。
但是,差异很小,因此您可能希望使用该库,因为它已经恢复生机(它从 2017 年起就已经死了)。但是您将不得不处理该库的奇怪的“前台没有窗口”异常,我的代码不会受到影响(请参阅基准代码中的代码注释)。
无论哪种方式......享受!
Mar*_*oma 12
以下脚本应适用于Linux,Windows和Mac.它目前仅在Linux(Ubuntu Mate Ubuntu 15.10)上测试过.
对于Linux:
安装wnck(sudo apt-get install python-wnck在Ubuntu上,请参阅libwnck.)
对于Windows:
确保win32gui可用
对于Mac:
确保AppKit可用
#!/usr/bin/env python
"""Find the currently active window."""
import logging
import sys
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
level=logging.DEBUG,
stream=sys.stdout)
def get_active_window():
"""
Get the currently active window.
Returns
-------
string :
Name of the currently active window.
"""
import sys
active_window_name = None
if sys.platform in ['linux', 'linux2']:
# Alternatives: http://unix.stackexchange.com/q/38867/4784
try:
import wnck
except ImportError:
logging.info("wnck not installed")
wnck = None
if wnck is not None:
screen = wnck.screen_get_default()
screen.force_update()
window = screen.get_active_window()
if window is not None:
pid = window.get_pid()
with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
active_window_name = f.read()
else:
try:
from gi.repository import Gtk, Wnck
gi = "Installed"
except ImportError:
logging.info("gi.repository not installed")
gi = None
if gi is not None:
Gtk.init([]) # necessary if not using a Gtk.main() loop
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
active_window = screen.get_active_window()
pid = active_window.get_pid()
with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
active_window_name = f.read()
elif sys.platform in ['Windows', 'win32', 'cygwin']:
# http://stackoverflow.com/a/608814/562769
import win32gui
window = win32gui.GetForegroundWindow()
active_window_name = win32gui.GetWindowText(window)
elif sys.platform in ['Mac', 'darwin', 'os2', 'os2emx']:
# http://stackoverflow.com/a/373310/562769
from AppKit import NSWorkspace
active_window_name = (NSWorkspace.sharedWorkspace()
.activeApplication()['NSApplicationName'])
else:
print("sys.platform={platform} is unknown. Please report."
.format(platform=sys.platform))
print(sys.version)
return active_window_name
print("Active window: %s" % str(get_active_window()))
Run Code Online (Sandbox Code Playgroud)
Nun*_*dré 10
真的没有必要为这样的任务导入任何外部依赖。Python 带有一个非常简洁的外部函数接口 - ctypes,它允许本地调用 C 共享库。它甚至包括最常见的 Win32 DLL 的特定绑定。
例如,要获取foregorund 窗口的PID:
import ctypes
from ctypes import wintypes
user32 = ctypes.windll.user32
h_wnd = user32.GetForegroundWindow()
pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(h_wnd, ctypes.byref(pid))
print(pid.value)
Run Code Online (Sandbox Code Playgroud)
对于Linux用户:提供的所有答案都需要其他模块,例如“ wx”,这些模块安装时会出现许多错误(“ pip”在构建时失败),但是我能够很容易地修改此解决方案-> 原始源代码。原始版本中存在错误(regex上为Python TypeError)
import sys
import os
import subprocess
import re
def get_active_window_title():
root = subprocess.Popen(['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout=subprocess.PIPE)
stdout, stderr = root.communicate()
m = re.search(b'^_NET_ACTIVE_WINDOW.* ([\w]+)$', stdout)
if m != None:
window_id = m.group(1)
window = subprocess.Popen(['xprop', '-id', window_id, 'WM_NAME'], stdout=subprocess.PIPE)
stdout, stderr = window.communicate()
else:
return None
match = re.match(b"WM_NAME\(\w+\) = (?P<name>.+)$", stdout)
if match != None:
return match.group("name").strip(b'"')
return None
if __name__ == "__main__":
print(get_active_window_title())
Run Code Online (Sandbox Code Playgroud)
优点是无需附加模块即可工作。如果您希望它可以在多个平台上运行,只需更改命令和regex字符串即可根据平台获取所需的数据(在sys.platform上方显示了标准的if / else平台检测)。
附带说明:import wnck仅在与“ sudo apt-get install python-wnck”一起安装时才与python2.x一起使用,因为我使用的是python3.x,所以唯一的选择是我尚未测试的pypie。希望这对其他人有帮助。
絢瀬絵*_*瀬絵里 -10
尝试使用 wxPython:
import wx
wx.GetActiveWindow()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29772 次 |
| 最近记录: |