Python实现剪切板实时监控与内容清洗实战

慢慢来
慢慢来
发布时间:2026-10-13 | 3人浏览过
原创

本文深入对比了Python中三种主流剪切板操作方式:pyperclip、win32clipboard及tkinter模块。通过源码分析与读写速度实测,指出win32clipboard在速度与多格式支持上的优势,同时揭示tkinter在Win10下的写入限制。基于性能最优的win32clipboard,实现了一个实时监测Ctrl+C事件、自动去除指定后缀及智能替换(如Python2转Python3)的剪切板监控小案例,并提供完整代码参考。

Python剪切板监控方案对比与实战案例

前言

在日常浏览网页时,复制粘贴是获取信息的高频操作。然而,用户意图复制的内容与最终粘贴出的结果往往存在偏差。数据从复制到粘贴的中间过程涉及系统层面的复杂处理,了解这些机制并掌握控制权显得尤为重要。

借助Python强大的生态,实现剪切板操作有多种路径。开发者可利用内置的ctypes模块、tk模块,或引入pyperclip、clipboard、pywin32.win32clipboard等第三方库。这些方案大多提供了封装良好且简洁的高级接口,便于直接调用。

出于对技术细节的严谨追求,本文对几种主流实现方式进行了深入的源码剖析与读写性能基准测试。最终,选取了读写速度最快的方案,构建了一个实时剪切板监控的示例程序,供读者参考与借鉴。

该示例程序主要实现以下功能:

实时监听Ctrl+C触发的剪切板写入事件,并自动剔除剪切板内容中指定的字符或文本片段,例如去除某些文字后的表情后缀(如(¬_¬)瞄)。

利用正则表达式对特定文本进行智能替换处理,例如自动将Python 2语法的代码转换为Python 3兼容格式。

主流剪切板操作模块源码与性能分析

方案一:调用第三方pyperclip模块


In [1]: import pyperclip
In [2]: data = pyperclip.paste()
In [3]: data
Out[3]: "print 'Hello World'\r\n————————————————\r\n版权声明:本文为CSDN博主「...」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。\r\n原文链接:https://blog.csdn.net/.../article/details/..."
In [4]: data = data[7:12]
In [5]: pyperclip.copy(data)
In [6]: pyperclip.paste()
Out[6]: 'Hello'

其底层源码基于内置ctypes模块中的ctypes.windll.user32接口编写,代码结构与pandas包中的实现一致,具体引用位置见pandas.io.clipboard.windows。代码引用如下


import ctypes
windll = ctypes.windll
safeGetClipboardData = CheckedCall(windll.user32.GetClipboardData)
safeGetClipboardData.argtypes = [UINT]
safeGetClipboardData.restype = HANDLE
safeSetClipboardData = CheckedCall(windll.user32.SetClipboardData)
safeSetClipboardData.argtypes = [UINT, HANDLE]
safeSetClipboardData.restype = HANDLE

优点:跨平台兼容性好,接口调用简洁方便。

缺点:仅支持UTF-8编码的文本数据格式,且在高频读写场景下性能表现较慢。

方案二:调用第三方win32clipboard模块


In [1]: import win32clipboard
 ...:
 ...: def clipboard_get():
 ...: """获取剪贴板数据"""
 ...: win32clipboard.OpenClipboard()
 ...: data = win32clipboard.GetClipboardData()
 ...: win32clipboard.CloseClipboard()
 ...: return data
 ...:
 ...: def clipboard_set(data):
 ...: """设置剪贴板数据"""
 ...: win32clipboard.OpenClipboard()
 ...: win32clipboard.SetClipboardData(13, data)
 ...: win32clipboard.CloseClipboard()
 ...: return True
 ...:
In [2]: data = clipboard_get()
In [3]: data
Out[3]: "print 'Hello World'\r\n————————————————\r\n版权声明:本文为CSDN博主「...」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 原文出处链接及本声明。\r\n原文链接:https://blog.csdn.net/.../article/details/..."

In [4]: clipboard_set(data[7:12])
Out[4]: True

In [5]: clipboard_get()
Out[5]: 'Hello'

该模块由C语言源码封装,Python接口调用方式如下


def GetClipboardData(*args, **kwargs): # real signature unknown 
 pass
def SetClipboardData(*args, **kwargs): # real signature unknown
 pass

优点:底层C语言封装使得读写速度达到最快,且支持多种剪切板数据格式。

缺点:仅限Windows平台使用;高频读写时易报错,需谨慎处理;对于UTF-8以外的数据格式,需熟悉winuser.h库并自行设计编写相关逻辑。

方案三:调用内置tkinter模块


In [1]: from tkinter import *
 ...:
 ...: r = Tk()

In [2]: data = r.clipboard_get()

In [3]: data
Out[3]: "print 'Hello World'\n————————————————\n版权声明:本文为CSDN博主「...」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 出处链接及本声明。\n原文链接:https://blog.csdn.net/.../article/details/..."

In [4]: r.clipboard_append(data[7:12])

In [5]: r.clipboard_get()
Out[6]: 'Hello'

注意事项:在Windows 10系统测试中发现,tkinter模块仅能读取剪切板数据,无法直接写入。若通过外部调用clipboard_board方法,系统剪切板进程会被tkinter接管并锁死,导致其他应用按Ctrl+V时出现卡死或粘贴内容为空的现象。

若坚持通过Tk()对象写入剪切板,必须采用延迟销毁Tk对象的方法,否则系统剪切板数据无法更新,内容仍为空(实测若设置0.2秒以内的读取频率,剪切板依然为空,实用性较低)。具体实现如下:


from tkinter import *
import time
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('some string')
r.update()
time.sleep(.2)
r.update()
r.destroy()

源码调用:C语言封装,Python接口调用方式如下


# 读取剪切板数据:
_tkinter.tkapp('clipboard', 'get')
# 写入剪切板数据:
_tkinter.tkapp('clipboard', 'append')

剪切板读写速度测试结果

基于win32clipboard的实时监测与内容清洗实现

实时监控小案例实现:


import win32clipboard
import re
import time
def clipboard_get():
  """获取剪贴板数据"""
  win32clipboard.OpenClipboard()
  data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
  win32clipboard.CloseClipboard()
  return data
def clipboard_set(data):
  """设置剪贴板数据"""
  win32clipboard.OpenClipboard()
  win32clipboard.EmptyClipboard()
  win32clipboard.SetClipboardData(win32clipboard.CF_UNICODETEXT, data)
  win32clipboard.CloseClipboard()
# 初始化替换字符列表,相比于正则使用replace函数进行单字符替换更快
char_list = [('(', '('),
       (')', ')'),
       ('“', '"'),
       ('”', '"'),
       ('‘', '\''),
       (''', '\''),
       ('print ', 'print '),
       ('版权声明:本文为CSDN', '版权声明:本文为CSDN'),
       ]
# 预编译正则替换匹配表达式
# 匹配python2格式的 print函数文本
sub_print = re.compile(r'\bprint\s+(.+)')
# 匹配csdn复制自带的版权声明后缀文本
sub_csdn = re.compile(r'—+\s+版权声明:本文为CSDN.*\s+原文链接.*')
# 指定场景 sub替换函数:python2格式的 print函数 替换为python3格式
def sub_fn(s):
  return 'print(' + s.group(1).strip() + ')\r\n'
# 判断如果没有要替换的字符则返回None,有则执行替换操作,先进行字符列表replace,再执行reg.sub(sub_fn, txt)
def char_replace_reg_sub(txt):
  new_txt = txt
  # 对字符列表中字符 逐一判断,如果字符在文本中 则replace替换,如果都不在 则return None,不用再进行替换操作
  i = 0
  for old_char, new_char in char_list:
    if old_char in new_txt:
      i += 1
      new_txt = new_txt.replace(old_char, new_char)
  if i == 0:
    return None

  print('-' * 150, '\n【After char replace】:', new_txt)
  # 对指定场景替换 使用正则re.sub
  new_txt = sub_print.sub(sub_fn, new_txt)
  new_txt = sub_csdn.sub('', new_txt)
  print('【After sub replace:】', new_txt)
  return new_txt


def main():
  """后台脚本:每隔0.2秒,读取剪切板文本,检查有无指定字符或字符串,如果有则执行替换"""
  # recent_txt 存放最近一次剪切板文本,初始化值只多执行一次paste函数读取和替换
  recent_txt = clipboard_get()
  replaced_txt = char_replace_reg_sub(recent_txt)
  clipboard_set(recent_txt if replaced_txt is None else replaced_txt)

  while True:
    # txt 存放当前剪切板文本
    txt = clipboard_get()

    # 剪切板内容和上一次对比如有变动,再进行内容判断,判断后如果发现有指定字符在其中的话,再执行替换
    if txt != recent_txt:
      # print(f'txt:{txt}')
      new_txt = char_replace_reg_sub(txt) # 没查到要替换的子串,返回None

      if new_txt is not None:
        clipboard_set(new_txt)
        # 更新 recent_txt 为替换之后的文本,便于下次与 txt 剪切板文本对比,判断内容有无更新
        recent_txt = new_txt
    # 检测间隔(延迟0.2秒)
    time.sleep(0.2)
if __name__ == '__main__':
  main()

运行效果展示:


-----------------------------------------------------------------------------------------
【Copy text】:

print 'Hello World' \r\n————————————————\r\n版权声明:本文为CSDN博主「...」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 原文出处链接及本声明。\r\n原文链接:https://blog.csdn.net/.../article/details/...)
-----------------------------------------------------------------------------------------
【After replace:】:

print('Hello World')
-----------------------------------------------------------------------------------------

参考链接:

微软官方开发文档:https://docs.microsoft.com/zh-cn/windows/win32/dataxchg/using-the-clipboard?redirectedfrom=MSDN#_win32_Copying_Information_to_the_Clipboard

Stack Overflow相关讨论:https://stackoverflow.com/questions/579687/how-do-i-copy-a-string-to-the-clipboard-on-windows-using-python

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表