TANKING 发布的文章

Python uiautomation

Python uiautomation 是一个用于自动化 GUI 测试和操作的库,它可以模拟用户操作来执行各种任务。通过这个库,可以使用Python脚本模拟人工点击,人工操作界面。本文使用 Python uiautomation 进行微信电脑版的操作。

微信电脑版

以下是本次实验的版本号。

2023-11-23T10:03:36.png

你需要安装 uiautomation

pip install uiautomation

然后使用 uiautomation 进行操作。

代码

import time

import uiautomation as auto
import re
from plyer import notification

notification_history = {} # 历史消息

def check_wechat_messages():

# 获取微信窗口
wechat_win = auto.WindowControl(Name="微信", ClassName="WeChatMainWndForPC")

shoukuanWin = wechat_win.ListControl(Name="会话")
bbb = shoukuanWin.GetChildren()

for chatMsg in bbb:
    if "条新消息" in chatMsg.Name:

        # 计算消息条数
        match = re.match(r'([a-zA-Z0-9]+)(\d+)条新消息', chatMsg.Name)

        if match:
            nickname = match.group(1)
            message_count = int(match.group(2))

            printInfo = f"{nickname} 给你发送了 {message_count} 条消息"
            print(printInfo)
            print("------------")

            # 获取消息列表控件
            xiaoxis = wechat_win.ListControl(Name="消息")
            
            # 获取消息列表控件的子控件
            xiaoxi_children = xiaoxis.GetChildren()

            # 获取最后一个子控件
            last_xiaoxi = xiaoxi_children[-1]

            # 打印最后一条消息的内容
            print(last_xiaoxi.Name)

            # 在指定时间内不重发
            last_notification_time = notification_history.get((nickname, message_count), 0)
            current_time = time.time()

            if current_time - last_notification_time > 15:

                # 依次发送
                notification_title = f"来自 {nickname} 的 {message_count} 条消息"
                notification_message = f"{last_xiaoxi.Name}"

                notification.notify(
                    title=notification_title,
                    message=notification_message,
                    app_name="WeChat"
                )

                # 更新日志
                notification_history[(nickname, message_count)] = current_time

if name == "__main__":

try:
    while True:
        check_wechat_messages()
        time.sleep(2)  #2秒检测一次UI组件
except KeyboardInterrupt:
    print("程序退出~")
except Exception as e:
    print(f"程序执行出现了问题: {str(e)}")

代码解析:

以上代码使用 uiautomation 实时获取微信聊天列表的消息状态,一旦有消息发过来,就会获取到发送人的微信昵称以及发送的消息内容、消息个数。

2023-11-23T10:04:11.png

每2秒获取一次UI控件的内容,实测挂在后台对CPU和内存占用并无明显影响。

结合Python uiautomation的各种用法,可以做成自动回复的功能。

UISpy.exe

使用这款软件,可以获取到微信电脑版大部分控件的内容。

例如:微信聊天列表、群名称、好友微信昵称、群人数、微信号等。

2023-11-23T10:04:29.png

还可以获取到群内的每一条聊天内容,获取到你跟好友的聊天记录。

2023-11-23T10:04:42.png

只要UISpy.exe可获取到的控件内容,那么你用 Python就可以获取到。

摘要

要在微信分享卡片,需要接入微信自家的JSSDK,比较麻烦,还需要认证公众号,但是如果你没有这样的条件,那么你也可以试试使用iOS的Safari浏览器轻松实现,只需要在html中加入3个meta即可。

代码

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover, minimum-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="renderer" content="webkit">
    <meta name="layoutmode" content="standard">
    <meta name="imagemode" content="force">
    <meta name="wap-font-scale" content="no">
    <meta name="format-detection" content="telephone=no">
    <title>引流宝</title>
    <link rel="icon" href="http://dingyue.ws.126.net/2023/1117/12d3b6e5j00s49moi0138d000u000u0p.jpg">
    <meta name="description" content="11111111111111111">
    <meta property="og:type" content="website">
    <meta property="og:title" content="私域引流宝">
    <meta property="og:description" content="引流宝致力于为个人、团队提供基于微信私域流量的推广、引流的效率工具。">
    <meta property="og:image" content="http://dingyue.ws.126.net/2023/1117/12d3b6e5j00s49moi0138d000u000u0p.jpg">
    <meta property="og:url" content="https://githubfast.com/likeyun/liKeYun_Ylb">
</head>

<body>
    请在Safari浏览器点击分享到微信!
</body>

是哪三个meta?

<meta property="og:title" content="私域引流宝">


分别是标题、摘要、图片。

配置了这三个,直接在Safari浏览器分享出去,就是卡片了。

2023-11-23T10:02:05.png

作者

TANKING

摘要

数据库操作类可以封装数据库连接和操作,使代码更易于维护和扩展。它们提供了一种组织代码的方法,将数据库相关的功能放在一个类中,以便于复用。

良好的数据库操作类可以提供一定程度的安全性,通过参数化查询或准备语句来防止SQL注入攻击。这有助于保护数据库免受恶意输入的影响。

良好的数据库操作类可以提供一定程度的安全性,通过参数化查询或准备语句来防止SQL注入攻击。这有助于保护数据库免受恶意输入的影响。

数据库操作类有助于提高PHP应用程序的可维护性、安全性和性能,同时促进代码的重用和更好的代码组织。然而,选择适合项目需求的数据库操作类以及正确使用它们非常重要。

Database.php

<?php

/**
 * PHP PDO MySQL数据库操作类
 * 作者:TANKING
 * 时间:2023-10-12
 * 博客:https://segmentfault.com/u/tanking
 */

class DB_API {
    private $pdo;
    private $error;
    
    // 连接数据库
    public function __construct($config) {
        $dsn = "mysql:host={$config['db_host']};port={$config['db_port']};dbname={$config['db_name']}";
        try {
            $this->pdo = new PDO($dsn, $config['db_user'], $config['db_pass']);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
        }
    }
    
    // 插入
    public function add($table, $data) {
        try {
            $columns = implode(', ', array_keys($data));
            $values = implode(', :', array_keys($data));
            $query = "INSERT INTO $table ($columns) VALUES (:$values)";
            $stmt = $this->pdo->prepare($query);
            $stmt->execute($data);
            return $this->pdo->lastInsertId();
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
            return false;
        }
    }
    
    // 更新
    public function update($table, $where, $data) {
        try {
            
            // 构建SET子句
            $set = '';
            foreach ($data as $key => $value) {
                $set .= "$key = :$key, ";
            }
            $set = rtrim($set, ', ');
    
            // 构建WHERE子句
            $whereClause = '';
            foreach ($where as $key => $value) {
                $whereClause .= "$key = :where_$key AND ";
            }
            $whereClause = rtrim($whereClause, 'AND ');
    
            // 构建SQL查询
            $query = "UPDATE $table SET $set WHERE $whereClause";
    
            // 创建预处理语句
            $stmt = $this->pdo->prepare($query);
    
            // 绑定更新数据的参数
            foreach ($data as $key => $value) {
                $stmt->bindValue(":$key", $value);
            }
    
            // 绑定WHERE条件的参数
            foreach ($where as $key => $value) {
                $stmt->bindValue(":where_$key", $value);
            }

            // 执行预处理语句
            $stmt->execute();
            
            // 操作成功
            return true;
    
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
            
            // 操作失败
            return false;
        }
    }

    // 删除
    public function delete($table, $where, $params = array()) {
        try {
            // 构建WHERE子句
            $whereClause = '';
            foreach ($where as $key => $value) {
                $whereClause .= "$key = :$key AND ";
            }
            $whereClause = rtrim($whereClause, 'AND ');
    
            // 构建SQL查询
            $query = "DELETE FROM $table WHERE $whereClause";
    
            // 创建预处理语句
            $stmt = $this->pdo->prepare($query);
    
            // 绑定WHERE条件的参数
            foreach ($where as $key => $value) {
                $stmt->bindValue(":$key", $value);
            }
    
            // 执行预处理语句
            $stmt->execute();
    
            // 操作成功
            return true;
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
            
            // 操作失败
            return false;
        }
    }

    // 查询
    public function select($table, $fields = "*", $conditions = null, $likeConditions = null, $orderBy = null, $limit = null, $params = array()) {
        try {
            // 构建SELECT子句
            if (is_array($fields)) {
                $fields = implode(', ', $fields);
            } elseif ($fields === "*") {
                $fields = "*";
            } else {
                $fields = "";
            }
    
            // 构建WHERE子句
            $whereClause = '';
            if (!is_null($conditions) && is_array($conditions)) {
                foreach ($conditions as $key => $value) {
                    $whereClause .= "$key = :$key AND ";
                }
                $whereClause = rtrim($whereClause, 'AND ');
            }
    
            // 合并LIKE条件
            if (!is_null($likeConditions) && is_array($likeConditions)) {
                if (!empty($whereClause)) {
                    $whereClause .= ' AND ';
                }
                foreach ($likeConditions as $key => $value) {
                    $whereClause .= "$key LIKE :like_$key AND ";
                    $params[":like_$key"] = $value;
                }
                $whereClause = rtrim($whereClause, 'AND ');
            }
    
            // 构建ORDER BY子句
            $orderByClause = '';
            if (!is_null($orderBy) && is_array($orderBy)) {
                $orderByClause = "ORDER BY " . implode(', ', $orderBy);
            }
    
            // 构建LIMIT子句
            $limitClause = '';
            if (!is_null($limit)) {
                $limitClause = "LIMIT $limit";
            }
    
            // 构建SQL查询
            $query = "SELECT $fields FROM $table";
            if (!empty($whereClause)) {
                $query .= " WHERE $whereClause";
            }
            if (!empty($orderByClause)) {
                $query .= " $orderByClause";
            }
            if (!empty($limitClause)) {
                $query .= " $limitClause";
            }
    
            // 创建预处理语句
            $stmt = $this->pdo->prepare($query);
    
            // 绑定参数
            if (!is_null($conditions) && is_array($conditions)) {
                foreach ($conditions as $key => $value) {
                    $stmt->bindValue(":$key", $value);
                }
            }
            
            if (!is_null($likeConditions) && is_array($likeConditions)) {
                foreach ($likeConditions as $key => $value) {
                    $stmt->bindValue(":like_$key", $value);
                }
            }
    
            // 执行预处理语句
            $stmt->execute();
    
            // 获取查询结果
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
            return $result; // 返回查询结果数组
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
            return false; // 操作失败
        }
    }

    // 执行原生SQL语句
    public function execQuery($query, $params = array()) {
        try {
            // 创建预处理语句
            $stmt = $this->pdo->prepare($query);
    
            // 绑定参数
            foreach ($params as $key => $value) {
                $stmt->bindValue($key, $value);
            }
    
            // 执行预处理语句
            $stmt->execute();
            
            // 操作成功
            return true;
        } catch (PDOException $e) {
            $this->error = $e->getMessage();
            
            // 操作失败
            return false;
        }
    }

    // 错误信息
    public function errorMsg() {
        return $this->error;
    }
}