你的代码肯定是有问题的:
1.你不理解我们的console需要接受回车键入的时候一定是在前端的,后端的窗口浏览器怎么可能获得焦点,这个实际上需要用户立即切换窗口,这个不合理。不如你去捕捉用户的鼠标事件?你有什么好办法?
2.你的这个输出似乎都不对,拷贝要获得焦点才能行,而这个操作是否是依赖于鼠标拖拽呢?这个不重要,我有一个解决方法是要找到对话的内容的顶部的修改,但是这个更加的复杂,需要你点击顶部标题触发修改标题的对话框,这样子再拷贝,我感觉这个更加的复杂,
3.不管怎么说,我先在看到xdotool在移动鼠标,但是拷贝的内容呢?你有操作键盘的ctrl+c吗?还是说xclip有安全性考量不给你粘贴?
nick@nick-sager:~/workspace/RPA$ python ./combine.py
/home/nick/.local/lib/python3.10/site-packages/torch/cuda/__init__.py:61: FutureWarning: The pynvml package is deprecated. Please install nvidia-ml-py instead. If you did not install pynvml directly, please report this to the maintainers of the package that installed pynvml for you.
import pynvml # type: ignore[import]
========================================
📸 按回车键触发实时截屏(确保目标窗口在前台)
========================================
✅ 已截取屏幕:/home/nick/workspace/RPA/real_time_screenshot.png
✅ 验证图已保存:/home/nick/workspace/RPA/real_time_ocr_verify.png
✅ 识别到 24 个列表项
========================================
📋 3秒后开始拷贝,请立刻切回目标窗口!
========================================
🔹 处理列表项 1(坐标:199,144):
✅ 拷贝成功:import cv2
import easyocr
import numpy as np
import warnings
import subprocess
import time
import os
warnings.filterwarnings("ignore")
# ========== 全局配置(根据你的屏幕/列表调整) ==========
# 对话列表的大致区域(不用精准,OCR会自动识别)
LIST_X1, LIST_X2 = 30, 400 # 列表X范围
LIST_Y1, LIST_Y2 = 80, 1000 # 列表Y范围
OUTPUT_IMG_PATH = "/home/nick/workspace/RPA/real_time_ocr_verify.png"
SCREENSHOT_PATH = "/home/nick/workspace/RPA/real_time_screenshot.png"
DRAG_OFFSET = 100 # 拖拽宽度(覆盖文字长度)
COPY_DELAY = 3 # 拷贝前的窗口切换时间(秒)
# ========== 初始化EasyOCR ==========
reader = easyocr.Reader(
lang_list=['ch_sim', 'en'],
gpu=False,
verbose=False,
model_storage_directory="/home/nick/.EasyOCR/model"
)
# ========== 函数1:实时截屏 ==========
def capture_screen():
"""截取整个屏幕并返回图片"""
subprocess.run(["scrot", SCREENSHOT_PATH], check=True, capture_output=True)
img = cv2.imread(SCREENSHOT_PATH)
if img is None:
raise Exception("❌ 无法读取截屏图片")
print(f"✅ 已截取屏幕:{SCREENSHOT_PATH}")
return img
# ========== 函数2:OCR识别列表坐标 ==========
def ocr_list_coordinates(img):
"""识别列表项中心坐标,返回坐标列表+带标记的验证图"""
# 裁剪列表区域
crop_img = img[LIST_Y1:LIST_Y2, LIST_X1:LIST_X2]
gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)
# OCR识别
result = reader.readtext(gray, detail=1)
# 过滤无效结果,提取坐标
list_coords = []
img_verify = img.copy()
for (bbox, text, conf) in result:
text = text.strip()
# 过滤规则:排除纯问号/高问号占比/过短文本
if all(c == '?' for c in text) or len(text) < 2 or text.count('?')/len(text) > 0.5:
continue
# 计算屏幕绝对坐标
center_x = int((bbox[0][0] + bbox[2][0])/2 + LIST_X1)
center_y = int((bbox[0][1] + bbox[2][1])/2 + LIST_Y1)
list_coords.append((center_x, center_y))
# 可视化标记
cv2.circle(img_verify, (center_x, center_y), 5, (0,0,255), -1)
cv2.putText(img_verify, f"({center_x},{center_y})",
(center_x+10, center_y), cv2.FONT_HERSHEY_SIMPLEX,
0.4, (0,0,255), 1)
# 保存验证图
cv2.imwrite(OUTPUT_IMG_PATH, img_verify)
print(f"✅ 验证图已保存:{OUTPUT_IMG_PATH}")
print(f"✅ 识别到 {len(list_coords)} 个列表项")
return list_coords
# ========== 函数3:读取剪贴板 ==========
def get_clipboard_text():
"""读取系统剪贴板内容"""
try:
result = subprocess.run(["xclip", "-o", "-selection", "clipboard"],
capture_output=True, text=True, check=True)
return result.stdout.strip()
except:
return ""
# ========== 函数4:拖拽选中+拷贝文字 ==========
def copy_list_item_text(center_coords):
"""批量拷贝列表项文字"""
print(f"\n========================================")
print(f"📋 {COPY_DELAY}秒后开始拷贝,请立刻切回目标窗口!")
print(f"========================================")
time.sleep(COPY_DELAY)
copied_results = []
for idx, (x, y) in enumerate(center_coords, 1):
print(f"\n🔹 处理列表项 {idx}(坐标:{x},{y}):")
# 1. 移动到文字左侧
subprocess.run(["xdotool", "mousemove", str(x - DRAG_OFFSET), str(y)])
time.sleep(0.2)
# 2. 拖拽选中文字
subprocess.run(["xdotool", "mousedown", "1"])
time.sleep(0.2)
subprocess.run(["xdotool", "mousemove", str(x + DRAG_OFFSET), str(y)])
time.sleep(0.2)
subprocess.run(["xdotool", "mouseup", "1"])
time.sleep(0.2)
# 3. Ctrl+C拷贝
subprocess.run(["xdotool", "key", "ctrl+c"])
time.sleep(0.2)
# 4. 读取并保存结果
text = get_clipboard_text()
copied_results.append({
"index": idx,
"coords": (x, y),
"text": text
})
# 输出结果
if text:
print(f"✅ 拷贝成功:{text}")
else:
print(f"❌ 拷贝失败")
return copied_results
# ========== 主函数:串联所有操作 ==========
def main():
try:
# 步骤1:等待用户触发截屏
print("========================================")
print("📸 按回车键触发实时截屏(确保目标窗口在前台)")
print("========================================")
input()
# 步骤2:实时截屏
screen_img = capture_screen()
# 步骤3:OCR识别列表坐标
list_coords = ocr_list_coordinates(screen_img)
if not list_coords:
print("❌ 未识别到任何列表项")
return
# 步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Exception as e:
print(f"\n❌ 执行失败:{str(e)}")
if __name__ == "__main__":
main()
🔹 处理列表项 2(坐标:199,197):
✅ 拷贝成功:import cv2
import easyocr
import numpy as np
import warnings
import subprocess
import time
import os
warnings.filterwarnings("ignore")
# ========== 全局配置(根据你的屏幕/列表调整) ==========
# 对话列表的大致区域(不用精准,OCR会自动识别)
LIST_X1, LIST_X2 = 30, 400 # 列表X范围
LIST_Y1, LIST_Y2 = 80, 1000 # 列表Y范围
OUTPUT_IMG_PATH = "/home/nick/workspace/RPA/real_time_ocr_verify.png"
SCREENSHOT_PATH = "/home/nick/workspace/RPA/real_time_screenshot.png"
DRAG_OFFSET = 100 # 拖拽宽度(覆盖文字长度)
COPY_DELAY = 3 # 拷贝前的窗口切换时间(秒)
# ========== 初始化EasyOCR ==========
reader = easyocr.Reader(
lang_list=['ch_sim', 'en'],
gpu=False,
verbose=False,
model_storage_directory="/home/nick/.EasyOCR/model"
)
# ========== 函数1:实时截屏 ==========
def capture_screen():
"""截取整个屏幕并返回图片"""
subprocess.run(["scrot", SCREENSHOT_PATH], check=True, capture_output=True)
img = cv2.imread(SCREENSHOT_PATH)
if img is None:
raise Exception("❌ 无法读取截屏图片")
print(f"✅ 已截取屏幕:{SCREENSHOT_PATH}")
return img
# ========== 函数2:OCR识别列表坐标 ==========
def ocr_list_coordinates(img):
"""识别列表项中心坐标,返回坐标列表+带标记的验证图"""
# 裁剪列表区域
crop_img = img[LIST_Y1:LIST_Y2, LIST_X1:LIST_X2]
gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)
# OCR识别
result = reader.readtext(gray, detail=1)
# 过滤无效结果,提取坐标
list_coords = []
img_verify = img.copy()
for (bbox, text, conf) in result:
text = text.strip()
# 过滤规则:排除纯问号/高问号占比/过短文本
if all(c == '?' for c in text) or len(text) < 2 or text.count('?')/len(text) > 0.5:
continue
# 计算屏幕绝对坐标
center_x = int((bbox[0][0] + bbox[2][0])/2 + LIST_X1)
center_y = int((bbox[0][1] + bbox[2][1])/2 + LIST_Y1)
list_coords.append((center_x, center_y))
# 可视化标记
cv2.circle(img_verify, (center_x, center_y), 5, (0,0,255), -1)
cv2.putText(img_verify, f"({center_x},{center_y})",
(center_x+10, center_y), cv2.FONT_HERSHEY_SIMPLEX,
0.4, (0,0,255), 1)
# 保存验证图
cv2.imwrite(OUTPUT_IMG_PATH, img_verify)
print(f"✅ 验证图已保存:{OUTPUT_IMG_PATH}")
print(f"✅ 识别到 {len(list_coords)} 个列表项")
return list_coords
# ========== 函数3:读取剪贴板 ==========
def get_clipboard_text():
"""读取系统剪贴板内容"""
try:
result = subprocess.run(["xclip", "-o", "-selection", "clipboard"],
capture_output=True, text=True, check=True)
return result.stdout.strip()
except:
return ""
# ========== 函数4:拖拽选中+拷贝文字 ==========
def copy_list_item_text(center_coords):
"""批量拷贝列表项文字"""
print(f"\n========================================")
print(f"📋 {COPY_DELAY}秒后开始拷贝,请立刻切回目标窗口!")
print(f"========================================")
time.sleep(COPY_DELAY)
copied_results = []
for idx, (x, y) in enumerate(center_coords, 1):
print(f"\n🔹 处理列表项 {idx}(坐标:{x},{y}):")
# 1. 移动到文字左侧
subprocess.run(["xdotool", "mousemove", str(x - DRAG_OFFSET), str(y)])
time.sleep(0.2)
# 2. 拖拽选中文字
subprocess.run(["xdotool", "mousedown", "1"])
time.sleep(0.2)
subprocess.run(["xdotool", "mousemove", str(x + DRAG_OFFSET), str(y)])
time.sleep(0.2)
subprocess.run(["xdotool", "mouseup", "1"])
time.sleep(0.2)
# 3. Ctrl+C拷贝
subprocess.run(["xdotool", "key", "ctrl+c"])
time.sleep(0.2)
# 4. 读取并保存结果
text = get_clipboard_text()
copied_results.append({
"index": idx,
"coords": (x, y),
"text": text
})
# 输出结果
if text:
print(f"✅ 拷贝成功:{text}")
else:
print(f"❌ 拷贝失败")
return copied_results
# ========== 主函数:串联所有操作 ==========
def main():
try:
# 步骤1:等待用户触发截屏
print("========================================")
print("📸 按回车键触发实时截屏(确保目标窗口在前台)")
print("========================================")
input()
# 步骤2:实时截屏
screen_img = capture_screen()
# 步骤3:OCR识别列表坐标
list_coords = ocr_list_coordinates(screen_img)
if not list_coords:
print("❌ 未识别到任何列表项")
return
# 步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Exception as e:
print(f"\n❌ 执行失败:{str(e)}")
if __name__ == "__main__":
main()
🔹 处理列表项 3(坐标:173,234):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 4(坐标:259,257):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 5(坐标:218,293):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 6(坐标:225,332):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 7(坐标:260,370):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 8(坐标:227,408):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 9(坐标:260,446):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 10(坐标:258,484):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 11(坐标:266,522):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 12(坐标:259,560):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 13(坐标:268,598):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 14(坐标:252,636):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 15(坐标:266,673):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 16(坐标:232,713):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 17(坐标:328,711):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 18(坐标:265,750):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 19(坐标:210,788):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 20(坐标:274,826):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 21(坐标:249,864):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 22(坐标:266,902):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 23(坐标:269,940):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🔹 处理列表项 24(坐标:269,978):
✅ 拷贝成功:步骤4:自动拷贝所有列表项文字
copy_list_item_text(list_coords)
print("\n🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。")
except Ex
🎉 所有操作完成!验证图可查看坐标标记,拷贝结果已输出。
nick@nick-sager:~/workspace/RPA$