用脚本实现跨设备剪贴板

wen 实用脚本 3

本文目录导读:

用脚本实现跨设备剪贴板

  1. 方案一:局域网跨设备剪贴板(推荐)
  2. 方案二:使用现有工具
  3. 方案三:简单Web版(浏览器访问)

局域网跨设备剪贴板(推荐)

服务端(接收端)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
跨设备剪贴板 - 服务端(接收端)
运行在需要接收剪贴板内容的设备上
"""
import socket
import threading
import pyperclip
import json
import time
from datetime import datetime
class ClipboardServer:
    def __init__(self, host='0.0.0.0', port=8888):
        self.host = host
        self.port = port
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.clients = []
        self.running = True
    def start(self):
        """启动服务器"""
        try:
            self.server_socket.bind((self.host, self.port))
            self.server_socket.listen(5)
            print(f"✋ 剪贴板服务器已启动: {self.host}:{self.port}")
            print("等待其他设备连接...")
            # 启动接收线程
            accept_thread = threading.Thread(target=self.accept_clients)
            accept_thread.daemon = True
            accept_thread.start()
            # 主循环,监听剪贴板变化
            self.monitor_clipboard()
        except Exception as e:
            print(f"❌ 服务器错误: {e}")
            self.running = False
    def accept_clients(self):
        """接受客户端连接"""
        while self.running:
            try:
                client_socket, address = self.server_socket.accept()
                client_id = f"{address[0]}:{address[1]}"
                self.clients.append(client_socket)
                print(f"✅ 新设备连接: {client_id}")
                print(f"📊 当前连接数: {len(self.clients)}")
                # 启动接收该客户端数据的线程
                client_thread = threading.Thread(target=self.handle_client, args=(client_socket, address))
                client_thread.daemon = True
                client_thread.start()
            except:
                break
    def handle_client(self, client_socket, address):
        """处理客户端数据"""
        try:
            while self.running:
                data = client_socket.recv(4096)
                if not data:
                    break
                # 解码并设置剪贴板
                try:
                    content = data.decode('utf-8')
                    pyperclip.copy(content)
                    print(f"📋 [{datetime.now().strftime('%H:%M:%S')}] 收到剪贴板内容: {content[:50]}...")
                    # 广播给其他客户端(可选)
                    self.broadcast(content, client_socket)
                except Exception as e:
                    print(f"⚠️ 处理数据错误: {e}")
        except Exception as e:
            print(f"❌ 客户端连接断开: {e}")
        finally:
            if client_socket in self.clients:
                self.clients.remove(client_socket)
            client_socket.close()
    def broadcast(self, content, exclude_socket):
        """广播消息给其他客户端"""
        for client in self.clients[:]:
            if client != exclude_socket:
                try:
                    client.send(content.encode('utf-8'))
                except:
                    self.clients.remove(client)
    def monitor_clipboard(self):
        """监听本地剪贴板变化"""
        last_content = pyperclip.paste()
        print("📋 正在监听本地剪贴板...")
        print("按 Ctrl+C 退出")
        while self.running:
            try:
                current = pyperclip.paste()
                if current != last_content and current:
                    print(f"📋 本地剪贴板变化: {current[:50]}...")
                    # 广播给所有客户端
                    self.broadcast(current, None)
                last_content = current
                time.sleep(1)  # 1秒检查一次
            except KeyboardInterrupt:
                print("\n👋 服务器关闭")
                self.running = False
                break
            except Exception as e:
                print(f"⚠️ 监听错误: {e}")
                last_content = pyperclip.paste()
    def stop(self):
        """停止服务器"""
        self.running = False
        for client in self.clients:
            client.close()
        self.server_socket.close()
def main():
    print("=" * 50)
    print("跨设备剪贴板 - 服务端")
    print("=" * 50)
    # 使用默认配置或从环境变量读取
    host = input(f"监听地址 (默认: 0.0.0.0): ").strip() or '0.0.0.0'
    port = input(f"端口 (默认: 8888): ").strip() or '8888'
    port = int(port)
    server = ClipboardServer(host, port)
    try:
        server.start()
    except KeyboardInterrupt:
        print("\n👋 程序退出")
    finally:
        server.stop()
if __name__ == "__main__":
    main()

客户端(发送端)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
跨设备剪贴板 - 客户端(发送端)
运行在需要发送剪贴板内容的设备上
"""
import socket
import pyperclip
import threading
import time
from datetime import datetime
class ClipboardClient:
    def __init__(self, server_host, server_port=8888):
        self.server_host = server_host
        self.server_port = server_port
        self.socket = None
        self.running = True
        self.last_content = ""
    def connect(self):
        """连接到服务器"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.server_host, self.server_port))
            print(f"✅ 已连接到服务器: {self.server_host}:{self.server_port}")
            # 启动接收线程(可选)
            recv_thread = threading.Thread(target=self.receive_data)
            recv_thread.daemon = True
            recv_thread.start()
            return True
        except Exception as e:
            print(f"❌ 连接失败: {e}")
            return False
    def receive_data(self):
        """接收服务器广播的数据"""
        try:
            while self.running:
                data = self.socket.recv(4096)
                if data:
                    content = data.decode('utf-8')
                    print(f"📋 收到数据: {content[:50]}...")
                    # 可选:更新剪贴板
                    pyperclip.copy(content)
        except:
            pass
    def send_clipboard(self):
        """发送剪贴板内容"""
        last_content = pyperclip.paste()
        print("📋 监听剪贴板变化...")
        print("按 Ctrl+C 退出")
        while self.running:
            try:
                current = pyperclip.paste()
                if current != last_content and current:
                    # 发送剪贴板内容
                    self.socket.send(current.encode('utf-8'))
                    print(f"📤 [{datetime.now().strftime('%H:%M:%S')}] 已发送: {current[:50]}...")
                last_content = current
                time.sleep(1)  # 1秒检查一次
            except KeyboardInterrupt:
                print("\n👋 客户端退出")
                self.running = False
                break
            except Exception as e:
                print(f"⚠️ 发送错误: {e}")
                # 尝试重连
                if self.running:
                    print("🔄 尝试重新连接...")
                    self.running = False
                    time.sleep(3)
                    break
    def stop(self):
        """停止客户端"""
        self.running = False
        if self.socket:
            self.socket.close()
def main():
    print("=" * 50)
    print("跨设备剪贴板 - 客户端")
    print("=" * 50)
    # 获取服务器地址
    server_host = input("请输入服务器IP地址: ").strip()
    if not server_host:
        print("❌ IP地址不能为空")
        return
    port = input(f"端口 (默认: 8888): ").strip() or '8888'
    port = int(port)
    client = ClipboardClient(server_host, port)
    try:
        if client.connect():
            client.send_clipboard()
    except KeyboardInterrupt:
        print("\n👋 程序退出")
    finally:
        client.stop()
if __name__ == "__main__":
    main()

使用说明

安装依赖

pip install pyperclip

启动服务端(接收端)

python clipboard_server.py

启动客户端(发送端)

python clipboard_client.py

使用流程

  1. 在接收端运行服务端程序
  2. 在发送端运行客户端程序并输入服务端IP后,会自动同步到其他设备

使用现有工具

如果您不想自己实现,可以使用以下现成的跨设备剪贴板工具:

  1. KDE Connect - Linux/Windows/Android 跨平台
  2. AirDroid - Windows/Android
  3. Pushbullet - 跨平台支持
  4. Syncthing - 文件同步,可作为备选方案

简单Web版(浏览器访问)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简单Web版跨设备剪贴板
"""
from flask import Flask, request, jsonify, render_template_string
import pyperclip
import threading
import time
app = Flask(__name__)
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>跨设备剪贴板</title>
    <meta charset="utf-8">
    <style>
        body { font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
        textarea { width: 100%; height: 200px; margin: 10px 0; }
        button { padding: 10px 20px; margin: 5px; }
        #status { color: green; }
    </style>
</head>
<body>
    <h1>📋 跨设备剪贴板</h1>
    <div id="status">已连接</div>
    <textarea id="content" placeholder="输入或粘贴内容..."></textarea>
    <br>
    <button onclick="send()">📤 发送</button>
    <button onclick="receive()">📥 接收</button>
    <button onclick="clearAll()">🗑️ 清空</button>
    <script>
        async function send() {
            let content = document.getElementById('content').value;
            let res = await fetch('/send', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({content: content})
            });
            let data = await res.json();
            document.getElementById('status').innerText = '✅ 发送成功';
        }
        async function receive() {
            let res = await fetch('/receive');
            let data = await res.json();
            document.getElementById('content').value = data.content;
            document.getElementById('status').innerText = '✅ 接收成功';
        }
        function clearAll() {
            document.getElementById('content').value = '';
            document.getElementById('status').innerText = '🗑️ 已清空';
        }
    </script>
</body>
</html>
'''
@app.route('/')
def index():
    return render_template_string(HTML_TEMPLATE)
@app.route('/send', methods=['POST'])
def send():
    data = request.json
    if data and 'content' in data:
        pyperclip.copy(data['content'])
        return jsonify({'status': 'ok'})
    return jsonify({'status': 'error'})
@app.route('/receive')
def receive():
    content = pyperclip.paste()
    return jsonify({'content': content})
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

使用方法:

pip install flask pyperclip
python clipboard_web.py

然后通过浏览器访问 http://设备IP:5000 即可使用。

选择哪种方案取决于您的具体需求,如果需要在局域网内频繁使用,推荐方案一;如果偶尔使用,Web方案更方便。

抱歉,评论功能暂时关闭!