我注意到 Firefox 中的无头选项会在后台运行 Firefox,而不会附加任何窗口,而且我还没有找到一种方法可以在后台运行 Firefox,同时仍保留 Firefox 窗口的 hwnd能够使用。
我开始使用
pyvda
来获取
AppView
Firefox,但是
pyvda.get_apps_by_z_order
没有返回任何内容,所以我写了这个,我能够找到两个hwnd,但其中一个都没有一个可见的窗口。我能够在没有条件 if 语句的情况下让其中之一显示在我的任务栏上。
更新...
使用任务管理器中显示的内容,我能够弄清楚这两个 hwnds 是下面的代码中显示的是具有相同 pid 的 Firefox 子进程。
from inspect import currentframe
from typing import Optional
from psutil import Process
from selenium.webdriver import Firefox, FirefoxOptions
from win32con import SW_SHOW
from win32gui import EnumWindows, GetWindowText, ShowWindow, IsWindowVisible
from win32process import GetWindowThreadProcessId as GetPID
def main():
def get_child_pid(process: Optional[Process] = None) -> Process | int:
nonlocal firefox
if process is None:
process = Process(pid = firefox.service.process.pid)
for child in process.children():
if child.name() == 'firefox.exe':
if len(child.children()):
process = get_child_pid(process = child)
else:
break
if currentframe().f_back.f_code.co_name == 'main':
return process.pid
return process
def enum_windows(hwnd: int, pid: int):
if GetPID(hwnd)[1] == pid and len(GetWindowText(hwnd)):
print(GetWindowText(hwnd), (visible := bool(IsWindowVisible(hwnd))), sep = ': ')
if visible:
ShowWindow(hwnd, SW_SHOW)
options = FirefoxOptions()
options.add_argument('--headless')
firefox = Firefox(options = options)
EnumWindows(enum_windows, get_child_pid())
# firefox.quit()
if __name__ == '__main__':
main()
我需要找到一种方法,能够在后台加载 Firefox,并使用一个有效的窗口,我可以从中获取 hwnd。
你遇到的问题是,虽然你可以用
--headless
参数启动 Firefox 并隐藏主窗口,但 Gecko 驱动程序(Selenium 用来与 Firefox 交互的程序)仍然需要一个窗口句柄来正常工作。
有几种方法可以解决这个问题:
1. 使用虚拟显示器:
你可以使用像
pyvirtualdisplay
这样的库创建一个虚拟显示器。这将创建一个虚拟的 X 服务器,Firefox 可以在上面运行,并有一个关联的窗口句柄,即使它对用户不可见。
from pyvirtualdisplay import Display
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
display = Display(visible=0, size=(800, 600))
display.start()
options = Options()
options.add_argument("--headless")
driver = webdriver.Firefox(options=options)
# 你的 Selenium 代码在这里
driver.quit()
display.stop()
2. 使用
xvfb
(仅限 Linux):
如果你在 Linux 系统上运行,你可以使用
xvfb
(X Virtual Framebuffer)。
xvfb
是一个虚拟的帧缓冲区 X 服务器,它在内存中执行所有的图形操作,而不显示任何屏幕输出。
xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" python your_script.py
在你的 Python 脚本中,你不需要对 Selenium 代码进行任何修改。
3. 不要使用
--headless
参数:
如果你只需要窗口句柄,并且不介意 Firefox 窗口在后台可见,你可以不使用
--headless
参数。然后,你可以使用
driver.minimize_window()
将窗口最小化到任务栏,使其不干扰你的工作流程。
from selenium import webdriver
driver = webdriver.Firefox()
driver.minimize_window()
# 你的 Selenium 代码在这里
driver.quit()
请注意,这些方法都有一些优缺点。虚拟显示器和
xvfb
会增加一些开销,但它们提供了更干净的解决方案。另一方面,不使用
--headless
参数更简单,但 Firefox 窗口将可见。你应该根据你的具体需求和环境选择最合适的方法。