吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6245|回复: 18
收起左侧

[原创工具] 折腾系列之油猴鼠标伴侣,有源文件【python打包的EXE】

  [复制链接]
Pwaerm 发表于 2023-1-7 16:06
本帖最后由 Pwaerm 于 2023-1-7 16:54 编辑

这个工具只对极小众的朋友有用


作用: 第三方软件调用它实现对鼠标的控制,比如在写油猴脚本时遇到网站采用了阿里无感人机识别时,如果鼠标键盘不动,用户的输入是无法通过的,这就需要油猴调用第三方软件控制鼠标或者键盘做动作。
以前尝试过apache+php+vbs,但它需要电脑安装apache环境和excel(VBS需要调用excel控件才能驱动鼠标)

打包好的EXE 开启后无界面,只在托盘区显示一个黑猫图标,右键点击可退出(仅在自己的电脑WIN11 64上测试过)。
2.png
3.png
所有文件(python源码,打包配置文件,打包好的EXE)下载地址:
1.png
链接:https://pan.baidu.com/s/1i3zbLuSaZX-RqoOX9eCYCA?pwd=ja40
提取码:ja40



使用方法:
# 参数为 click 原地点击
# 参数为 move xd yd 鼠标从当前位置移动
# 参数为 moveTo x y 鼠标移动到目标位置
# 参数为 moveAndClick x y 鼠标移动到目标位置,然后点击
# 参数为 write 要输入的内容 时为模拟键盘输入

cmd 执行举例 :
点击 屏幕上200 200的位置  pymouse.exe  click 200 200
js调用执行举例(Jquery):
$.post("http://127.0.0.1:2000", { type: "move", x: 200, y: 100 })
$.get("http://127.0.0.1:2000?type=move&x=200&y=100

还可以添加注册表后在JS中通过 pmouse:\\参数  的方式执行(反应慢,不推荐)


python源代码(我的测试环境 window11 64位 python3.11)
[Asm] 纯文本查看 复制代码
# 需要的依赖
# pip install pyautogui -i https://pypi.tuna.tsinghua.edu.cn/simple/
# pip install pillow
# pip install PyQt5
from PyQt5.QtWidgets import QSystemTrayIcon, QMainWindow, QApplication, QMenu, QAction, QMessageBox
from PyQt5.QtGui import QIcon, QPixmap
import pyautogui
import sys
import os
import socketserver
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib
import json
from threading import Thread
import socket
import time
import tkinter.messagebox
import ctypes


class TrayModel(QSystemTrayIcon):
    def __init__(self, Window):
        super(TrayModel, self).__init__()
        self.window = Window
        self.init_ui()

    def init_ui(self):
        # 初始化菜单
        self.menu = QMenu()
        self.quit_action = QAction('退出', self, triggered=self.quit_clock)
        self.menu.addAction(self.quit_action)
        self.setContextMenu(self.menu)
        self.setIcon(QIcon(os.path.dirname(__file__) + '/Pwaerm.ico'))
        self.icon = self.MessageIcon()

    def quit_clock(self):
        stop_thread(webThread)
        app.quit()


class HttpHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.deParams(self.path)

    def do_POST(self):
        params = self.rfile.read(int(
            self.headers['content-length'])).decode("utf-8")
        self.deParams(params)

    def deParams(self, _params):
        params = _params.split('&')
        try:
            args = []
            for _key in params:
                _v = _key.split("=")
                if (len(_v) == 2):
                    args.append(_v[1])
        except:
            args = []
        self._response(self.path, args)

    def _response(self, path, args):
        Thread(target=mouseHandler, args=(args,)).start()
        result = {"status": 1, "msg": "执行成功"}
        # result = mouseHandler(args)
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(result).encode())


def openServer(_port):
    httpd = HTTPServer(('', _port), HttpHandler)
    httpd.serve_forever()


def mouseHandler(args: list):
    print("参数为:", args)
    if len(args) > 0:
        if args[0] == "click":
            # 参数为 click 原地点击
            p = pyautogui.position()
            pyautogui.click(p.x, p.y)
        if args[0] == "clickPoint":
            # 参数为 clickPoint x y 点击指定坐标
            pyautogui.click(int(args[1]), int(args[2]))
        elif args[0] == 'move':
            # 参数为 move xd yd 鼠标从当前位置移动
            pyautogui.move(int(args[1]), int(args[2]), 0.2)
        elif args[0] == 'moveTo':
            # 参数为 moveTo x y 鼠标移动到目标位置
            pyautogui.moveTo(int(args[1]), int(args[2]), 0.2)
        elif args[0] == 'moveAndClick':
            # 参数为 moveAndClick x y 鼠标移动到目标位置,然后点击
            pyautogui.moveTo(int(args[1]), int(args[2]), 0.5)
            pyautogui.click(int(args[1]), int(args[2]))
        elif args[0] == 'write':
            # 参数为write时为模拟键盘输入
            pyautogui.typewrite(args[1], 0.2)
        result = {
            "status": 1,
            "msg": "success"
        }
    else:
        result = {
            "status": 0,
            "msg": "缺少参数"
        }
    return result


def net_is_used(port, ip='127.0.0.1'):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((ip, port))
        s.shutdown(2)
        print('%s:%d is used' % (ip, port))
        return True
    except:
        print('%s:%d is unused' % (ip, port))
        return False


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setFixedSize(300, 200)
        self.tray = TrayModel(self)
        self.tray.show()


def openServer(_port):
    print(_port)
    httpd = HTTPServer(('', _port), HttpHandler)
    httpd.serve_forever()


def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle("P娃儿猫助手v1.0")
    window.setFixedSize(200, 160)
    # Thread(target=openServer, args=(2000, )).start()
    if len(sys.argv[1:]):
        mouseHandler(sys.argv[1:])
    else:
        if not net_is_used(2000):
            webThread = Thread(target=openServer, args=(2000, )).start()
            window.setWindowIcon(
                QIcon(os.path.dirname(__file__) + '/Pwaerm.ico'))
            # window.show()
            sys.exit(app.exec_())
        else:
            print("端口已经被占用")
            icon = QIcon()
            icon.addPixmap(QPixmap(os.path.dirname(__file__) + '/Pwaerm.ico'))
            box = QMessageBox()
            box.setWindowIcon(icon)
            box.setWindowTitle("P娃儿猫提示:")
            box.setStandardButtons(QMessageBox.Ok)
            box.button(QMessageBox.Ok).setText("确定")
            box.setStyleSheet("QLabel{min-width: 260px;min-height:50}")
            box.setText("端口已经被占用,程序可能已经启动")
            box.exec_()
            # tkinter.messagebox.showinfo(title = 'P娃儿猫提示:', message = '端口已经被占用,程序可能已经启动。')




如下代码(JS)示例在百度首页点击 输入框,输入  52pj
浏览器的默认情况下,不允许https页面从http链接引用 javascript/css/plug-ins等资源。启动添加  –allow-running-insecure-content  这一参数会放行这些内容
或者在 edge:\\flags (edge浏览器为例)关闭Block insecure private network requests并重启浏览器即可。

[Asm] 纯文本查看 复制代码
function handlerByPmouse(_type, _x, _y) {
    $.get("http://127.0.0.1:2000?type=" + _type + "&x=" + _x + "&y=" + _y);    
}
function autoHandler() {
    var _node = $("#kw");
    console.log(_node);
    var x = window.screenLeft;
    var y = window.screenTop;
    var _p = _node.offset();
    var _x = x + _p.left + _node.width() * .2 + Math.random() * _node.width() * .6;
    var _y = y + _p.top + 110 + _node.height() * .2 + Math.random() * _node.height() * .6;
    handlerByPmouse("moveAndClick", Math.floor(_x), Math.floor(_y));
        setTimeout(()=>{
                handlerByPmouse("write", "52pj");
        },2000);
}
function init() {
    autoHandler()
}
if (typeof $ == 'undefined') {
    var s = document.createElement("script");
    s.onload = init;
    s.src = "https://cdn.bootcss.com/jquery/2.1.4/jquery.min.js";
    document.getElementsByTagName("HEAD")[0].appendChild(s);
} else {
    init();
}


格式工厂 屏幕录像20230107_163923 00_00_00-00_00_30.gif


免费评分

参与人数 6吾爱币 +13 热心值 +6 收起 理由
fanji1986916 + 1 + 1 我很赞同!
cjzzz + 2 + 1 好方法
zhu911 + 1 + 1 谢谢@Thanks!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wanfon + 1 + 1 热心回复!
chao8709 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Pwaerm 发表于 2023-1-12 17:50
本帖最后由 Pwaerm 于 2023-1-12 17:52 编辑

再来改进一版文件小一些的(PyQt5太大了)

[Asm] 纯文本查看 复制代码
import socket
import sys
import json
import tkinter.messagebox
import pyautogui
import os
from infi.systray import SysTrayIcon
from threading import Thread


def mouseHandler(args: list):
    print("参数为:", args)
    if len(args) > 0:
        try:
            if args[0] == "click":
                # 参数为 click 原地点击
                p = pyautogui.position()
                pyautogui.click(p.x, p.y)
            if args[0] == "clickPoint":
                # 参数为 clickPoint x y 点击指定坐标
                pyautogui.click(int(args[1]), int(args[2]))
            elif args[0] == 'move':
                # 参数为 move xd yd 鼠标从当前位置移动
                pyautogui.move(int(args[1]), int(args[2]), 0.2)
            elif args[0] == 'moveTo':
                # 参数为 moveTo x y 鼠标移动到目标位置
                pyautogui.moveTo(int(args[1]), int(args[2]), 0.2)
            elif args[0] == 'moveAndClick':
                # 参数为 moveAndClick x y 鼠标移动到目标位置,然后点击
                pyautogui.moveTo(int(args[1]), int(args[2]), 0.5)
                pyautogui.click(int(args[1]), int(args[2]))
            elif args[0] == 'write':
                # 参数为write时为模拟键盘输入
                pyautogui.typewrite(args[1], 0.2)
            result = {"status": 1, "msg": "success"}
        except:
            result = {"status": -1, "msg": "args error"}
    else:
        result = {"status": 0, "msg": "缺少参数"}
    return result


def socketHandler(_conn):
    # 获取http请求,获取到的请求格式就是以请求行,请求头等组成的字符串(每一行是以/r/n结尾)
    data = _conn.recv(1024).decode()
    print("---------------------")
    print(data)
    # 切割请求内容,并取出请求行,请求行内容为:请求类型 请求内容(/xxx) http/1.1
    request = data.split('\r\n')
    try:
        if data.find("POST", 0, 4) == 0:
            # 获取post参数
            params = request.pop()
        else:
            params = request[0].split("?")[1]
            params = params.split(" ")[0]
        params = params.split('&')
        args = []
        for _key in params:
            _v = _key.split("=")
            if (len(_v) == 2):
                args.append(_v[1])
    except:
        args = []
    result = mouseHandler(args)
    info = ('HTTP/1.1 200 OK\r\nContent-type: text/html\r\nAccess-Control-Allow-Origin:*\r\n\r\n' +
            json.dumps(result)).encode()
    # 发送给浏览器
    _conn.send(info)
    _conn.close()


def socketInit():
    s = socket.socket()
    try:
        s.bind(('', 2000))
    except:
        print("error")
        tkinter.messagebox.showinfo(
            title='P娃儿猫提示:', message='端口已经被占用,程序可能已经启动。')
        systray.shutdown()
    else:
        s.listen(3)
        print("socket init")
        # 循环接收连接
        while True:
            conn, addr = s.accept()
            print('Connect from', addr)
            # 将处理客户端请求的逻辑封装
            socketHandler(conn)


if len(sys.argv[1:]):
    mouseHandler(sys.argv[1:])
else:
    systray = SysTrayIcon(os.path.dirname(__file__) +
                          "/Pwaerm.ico", "P娃儿猫鼠标助手", ())
    systray.start()
    Thread(target=socketInit, daemon=True).start()


现在只有12M了

下载地址
下载地址.txt (86 Bytes, 下载次数: 9)
 楼主| Pwaerm 发表于 2023-1-8 09:49
caiyong2050 发表于 2023-1-8 09:37
这是做什么用的?没明白

主要用于浏览器插件(油猴脚本等),比如要自动化操作网页。
有人机检测的网站  javascript直接点击按钮或者输入文本是不起作用的,必须用鼠标键盘操作。

javascript 本身没有操作鼠标键盘的权限,所以就只能调用这个软件达到控制鼠标键盘的效果。

另外 .bat文件也没有操作鼠标键盘的权限,编写批处理文件时也可以调用它达到控制鼠标键盘的效果。
tamintan 发表于 2023-1-7 16:13
ghoob321 发表于 2023-1-7 17:31
感谢楼主分享
0420307 发表于 2023-1-7 18:18
感谢分享,
亲亲宝贝A静 发表于 2023-1-7 20:41
感谢分享学习
你太牛逼了 发表于 2023-1-7 22:55
不明白实用 还是感谢下
caiyong2050 发表于 2023-1-8 09:37
这是做什么用的?没明白
poseidon1748 发表于 2023-1-9 09:47
感谢分享
ysjd22 发表于 2023-1-10 07:09
谢谢。挺好的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-23 22:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表