You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中内嵌打开并独占控制外部应用?

实现Python对外部程序的精准控制(类Selenium效果)

核心思路

你要的不是真的把外部程序"内嵌"进Python进程,而是要对独立的外部程序进程实现窗口级别的独占控制——包括窗口捕获、精准输入、后台操作,这可以通过系统API封装库或动态插桩工具实现。


方案1:Windows平台用pywin32实现原生控制

这是Windows下最直接的方案,直接调用系统API实现窗口级精准操作:

1. 定位目标程序窗口

通过进程名或窗口标题获取窗口句柄(HWND):

import win32gui
import win32process
import win32api
import win32con

def get_window_handle(process_name):
    hwnd_list = []
    win32gui.EnumWindows(lambda hwnd, extra: extra.append(hwnd), hwnd_list)
    for hwnd in hwnd_list:
        if win32gui.IsWindowVisible(hwnd):
            _, pid = win32process.GetWindowThreadProcessId(hwnd)
            try:
                handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, pid)
                exe_name = win32process.GetModuleFileNameEx(handle, 0).split("\\")[-1]
                if exe_name.lower() == process_name.lower():
                    return hwnd
            except:
                continue
    return None

2. 窗口专属截图(非全屏)

仅截取目标窗口区域,无需捕获整个屏幕:

import win32ui
import numpy as np
from PIL import Image

def capture_window(hwnd):
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    width = right - left
    height = bottom - top

    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()

    save_bitmap = win32ui.CreateBitmap()
    save_bitmap.CreateCompatibleBitmap(mfc_dc, width, height)
    save_dc.SelectObject(save_bitmap)

    save_dc.BitBlt((0, 0), (width, height), mfc_dc, (0, 0), win32con.SRCCOPY)

    bmp_info = save_bitmap.GetInfo()
    bmp_str = save_bitmap.GetBitmapBits(True)
    img = Image.frombuffer('RGB', (bmp_info['bmWidth'], bmp_info['bmHeight']), bmp_str, 'raw', 'BGRX', 0, 1)

    # 释放资源
    win32gui.DeleteObject(save_bitmap.GetHandle())
    save_dc.DeleteDC()
    mfc_dc.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwnd_dc)

    return img

3. 后台精准点击(仅作用于目标窗口)

直接给目标窗口发送鼠标消息,无需前端聚焦:

def click_window(hwnd, x, y):
    # 转换为窗口客户区相对坐标
    client_x = x - win32gui.GetWindowRect(hwnd)[0]
    client_y = y - win32gui.GetWindowRect(hwnd)[1]
    
    l_param = win32api.MAKELONG(client_x, client_y)
    win32api.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
    win32api.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, l_param)

方案2:跨平台用PyAutoGUI+窗口定位优化

你之前用PyAutoGUI效果差,核心是没结合窗口范围限制:

import pygetwindow as gw
import pyautogui

# 获取目标窗口
target_window = gw.getWindowsWithTitle("目标程序标题")[0]

# 限制操作范围为目标窗口区域
pyautogui.FAILSAFE = False
pyautogui.moveTo(target_window.left + 50, target_window.top + 50)  # 窗口内相对位置

# 仅截取目标窗口截图
window_screenshot = pyautogui.screenshot(region=(target_window.left, target_window.top, target_window.width, target_window.height))

注意:此方案不支持完全后台(窗口最小化时无法操作),适合窗口可见但无需前端聚焦的场景。

方案3:进阶用Frida实现进程级深度控制

如果需要类似Selenium的内核级控制(比如拦截程序内部函数、读取内存),可以用动态插桩工具Frida:

import frida
import sys

# 附加到目标进程
session = frida.attach("target.exe")

# 编写插桩脚本(示例:拦截MessageBox函数)
script = session.create_script("""
Interceptor.attach(Module.findExportByName("user32.dll", "MessageBoxW"), {
    onEnter: function(args) {
        console.log("MessageBox触发,原文本:" + args[1].readUtf16String());
        // 修改弹窗文本
        args[1] = ptr("0x" + "Python注入修改的文本".toString("utf16").replace(/../g, "$& ").trim().replace(/ /g, ""));
    }
});
""")
script.load()

sys.stdin.read()
session.detach()

此方案门槛较高,但能实现最深度的程序控制,适合定制化需求。

关键注意事项

  • 真·内嵌外部程序几乎不可能:每个程序都是独立进程,所有方案本质是控制独立进程+窗口隔离
  • 后台运行限制:部分程序依赖窗口消息循环,完全隐藏窗口可能导致功能异常,可尝试以隐藏窗口模式启动
  • 权限要求:控制系统级程序需管理员权限,否则可能无法获取窗口句柄或注入进程

内容的提问来源于stack exchange,提问作者ACC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 03:10:33