首页 > 编程问答 >selenium.webdriver.Firefox 与 FirefoxOptions().add_argument('--headless') 不返回有效的 hwnd

selenium.webdriver.Firefox 与 FirefoxOptions().add_argument('--headless') 不返回有效的 hwnd

时间:2024-07-25 07:00:18浏览次数:10  
标签:python selenium-webdriver firefox headless

我注意到 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 窗口将可见。你应该根据你的具体需求和环境选择最合适的方法。

标签:python,selenium-webdriver,firefox,headless
From: 78788714

相关文章

  • 使用 python Flask 发送邮件中的图像
    我想发送一封包含html代码和图像的电子邮件但在gmail中它说图像已附加,我不想要这样,我只想要电子邮件正文中的图像。html_content=f"<imgsrc="cid:banner"alt=""style="width:80%;">"msg=MIMEMultipart('related')html_part=MIMEText(html_c......
  • 在 python requests modul 中,如何检查页面是否使用“POST”方法或“GET”方法
    如何使用python“requests”模块检查页面是否使用“GET”方法或“POST”方法。我期望输出为True或False,或者GET或Post预期代码:importrequestsurl=f"www.get_example.com"response=requests.get(url)ifresponse.check_get==True:print("get")你......
  • VS Code Python - 如果括号(括号、大括号等)未关闭,内联建议不起作用
    我遇到的问题是,当我在未闭合的括号或方括号“内部”开始变量名称时,VSCode将不会显示任何建议。但是,如果在键入变量名称之前闭合括号,则建议效果很好。如果我可以避免它,我宁愿不将自动完成括号关闭设置为True也不使用TabOut扩展。第一个屏幕截图显示建议在闭括号/方......
  • 在 Azure 上部署代码时使用 Python 的多处理模块是否有意义?
    我们的团队在Azure机器学习(AML)上部署了一个Python脚本来处理存储在Azure存储帐户上的文件。我们的管道由一个ForEach活动组成,该活动调用每个或列出的文件的Python脚本。从Azure数据工厂(ADF)运行它会触发多个单独的管道同时运行......
  • 我已成功安装 pypdf2 但无法将其导入到我的 python 文件中
    我已经成功安装了pypdf2模块,但在导入它时,我发现该模块丢失了。我尝试使用fromPyPDF2importPdfReader导入,但它不起作用此问题的各种解决方案是什么?在尝试导入PyPDF2时遇到问题。以下是可能导致此问题的一些常见原因和解决方案:安......
  • Python3打开图片时请求ConnectionResetError(10054)
    我试图从'http://xxx.jpg'之类的网站下载图片。代码:headers={'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/66.0.3359.139Safari/537.36'}url='http://xxx.jpg'resp......
  • Jupyter Notebook 环境中的 Python 版本不匹配
    我遇到Jupyter笔记本启动横幅中报告的Python版本与我在笔记本中查询python--version时显示的版本之间的差异。启动横幅指示Python3.11.9,但是当我运行!python--version时,它返回Python3.11.7。我所做的步骤:basecondahas3.11.7versio......
  • Python XML 解析:字符串中的“<”被阻塞
    我有一个使用ET.XMLParser来解析CppCheckXML报告文件的Python模块。当尝试解析字符串中包含“<”的XML元素中的属性之一时,它会令人窒息,它会将其解释为格式错误的XML,例如:<errormsg="Includefile<iostream>notfound.">(注意字符和“iostream”之间的空格必须放......
  • 任意几行代码要成为Python中的函数需要什么?
    我正在上一门计算机科学课,我的任务是创建一个程序来实现一个带有参数的函数。我的老师告诉我,下面的代码不是一个函数,这让我很困惑,对于将某些代码行归类为“函数”所需的条件,我感到很困惑。defgame(numbers,max_turns,pfl,tgl):turns=0flag=Falseprint("You......
  • 如何使用 Python 创建新的 Azure 订阅?
    我正在尝试使用PythonSDK以编程方式创建新的Azure订阅。我发现的对AzurePythonSDK的唯一引用是这个这是我最终得到的结果:importazure.mgmt.billingimportazure.mgmt.subscriptioncreds=AzureCliCredential()client_name='test'defcreat......