2024 年最新使用 ntwork 框架搭建企业微信机器人详细教程

news2024/12/25 12:36:05

NTWORK 概述

基于 PC 企业微信的 api 接口,支持收发文本、群@、名片、图片、文件、视频、链接卡片等。

下载安装 ntwork

pip install ntwork

国内源安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ntwork

企业微信版本下载

官方下载:https://dldir1.qq.com/wework/work_weixin/WeCom_4.0.8.6027.exe

简单基础案例

import sys
import ntwork

wework = ntwork.WeWork()

# 打开pc企业微信, smart: 是否管理已经登录的企业微信`在这里插入代码片`
wework.open(smart=True)

# 等待登录
wework.wait_login()

# 向文件助手发送一条消息
wework.send_text(conversation_id="FILEASSIST", content="hello, NtWork")

try:
    while True:
        pass
except KeyboardInterrupt:
    ntwork.exit_()
    sys.exit()

获取联系人列表、群列表

# -*- coding: utf-8 -*-
import sys
import ntwork

wework = ntwork.WeWork()

# 打开pc企业微信, smart: 是否管理已经登录的微信
wework.open(smart=True)

# 等待登录
wework.wait_login()

# 获取内部(同事)列表并输出
contacts = wework.get_inner_contacts()
print("内部(同事)联系人列表: ")
print(contacts)

# 获取外部(客户)列表并输出
contacts = wework.get_external_contacts()
print("外部(客户)联系人列表: ")
print(contacts)


# 获取群列表并输出
rooms = wework.get_rooms()
print("群列表: ")
print(rooms)


try:
    while True:
        pass
except KeyboardInterrupt:
    ntwork.exit_()
    sys.exit()

监听消息自动回复

import sys
import ntwork

wework = ntwork.WeWork()

# 打开pc企业微信, smart: 是否管理已经登录的微信
wework.open(smart=True)


# 注册消息回调
@wework.msg_register(ntwork.MT_RECV_TEXT_MSG)
def on_recv_text_msg(wework_instance: ntwork.WeWork, message):
    data = message["data"]
    sender_user_id = data["sender"]
    self_user_id = wework_instance.get_login_info()["user_id"]
    conversation_id: str = data["conversation_id"]

    # 判断消息不是自己发的并且不是群消息时,回复对方
    if sender_user_id != self_user_id and not conversation_id.startswith("R:"):
        wework_instance.send_text(conversation_id=conversation_id, 
                                  content=f"你发送的消息是: {data['content']}")


try:
    while True:
        pass
except KeyboardInterrupt:
    ntwork.exit_()
    sys.exit()

使用 fastapi 框架

通过 fastapi 的 swagger 在线文档可以很方便的管理 ntwork 接口:案例

常见问题解决方案

版本不匹配异常

如果出现ntwork.exception.WeWorkVersionNotMatchError异常异常, 请确认是否安装github上指定的企业微信版本,如果确认已经安装,还是报错,可以在代码中添加以下代码,跳过微信版本检测

import ntwork
ntwork.set_wework_exe_path(wework_version='4.0.8.6027') 

账号克隆登录

新建一些 ntwork.wework 实例,然后调用 open 方法。

import ntwork

# 多开3个微信
for i in range(3):
    wework = ntwork.WeWork()
    wework.open(smart=False)

更完善的多实例管理查看 fastapi_example例子

如何监听输出所有的消息

# 注册监听所有消息回调
import ntwork


@wework.msg_register(ntwork.MT_ALL)
def on_recv_text_msg(wework_instance: ntwork.WeWork, message):
    print("########################")
    print(message)

完全例子查看examples/msg_register_all.py

如何关闭 ntwork 日志

os.environ['NTWORK_LOG'] = "ERROR" 要在import ntwork前执行

# -*- coding: utf-8 -*-
import os
import sys
import time
os.environ['NTWORK_LOG'] = "ERROR"

import ntwork

如何关闭 cmd 窗口

先使用pip install pywin32 安装pywin32模块, 然后在代码中添加以下代码, 完整例子查看examples/cmd_close_event.py

import sys
import ntwork
import win32api

def on_exit(sig, func=None):
    ntwork.exit_()
    sys.exit()


# 当关闭cmd窗口时
win32api.SetConsoleCtrlHandler(on_exit, True)

Pyinstaller 打包 exe

使用 pyinstaller 打包 ntwork 项目,需要添加 --collect-data=ntwork 选项

打包成单个 exe 程序

pyinstaller -F --collect-data=ntwork main.py

将所有的依赖文件打包到一个目录中

pyinstaller -y --collect-data=ntwork main.py

打包 fastapi_example 示例,需要添加 --paths=. --collect-data=ntchat

pyinstaller -F --paths=. --collect-data=ntchat main.py

登录日志预览

2024-04-12 00:45:21,949 - WeWorkManager - INFO - initialize wework, version: 4.0.8.6027
2024-04-12 00:45:21,949 - WeWorkManager - DEBUG - new wework instance
2024-04-12 00:45:21,982 - WeWorkInstance - INFO - open wework pid: 57024
2024-04-12 00:45:23,671 - WeWorkManager - DEBUG - accept client_id: 1
2024-04-12 00:45:26,225 - WeWorkInstance - DEBUG - on recv message: {'data': {'account': '', 'acctid': 'WangPaiGeGe', 'avatar': 'https://wework.qpic.cn/wwpic3az/457956_UJkq5TJkTfCnA5x_1712341231/0', 'corp_id': '1970325052533916', 'document_root': 'C:\\Users\\Administrator\\Documents\\WXWork\\1688856738534700', 'email': '', 'job_name': '', 'mobile': '19561983930', 'nickname': '', 'pid': 57024, 'position': '', 'sex': 1, 'user_id': '1688856738534700', 'username': '王牌哥哥'}, 'type': 11026}
2024-04-12 00:45:26,241 - WeWorkInstance - INFO - login success, name: 王牌哥哥

私聊自动回复案例

import sys
import ntwork

wework = ntwork.WeWork()

# 打开 pc 企业微信, smart: 是否管理已经登录的微信
wework.open(smart=True)


# 注册消息回调
@wework.msg_register(ntwork.MT_RECV_TEXT_MSG)
def on_recv_text_msg(wework_instance: ntwork.WeWork, message):
    data = message["data"]
    sender_user_id = data["sender"]
    self_user_id = wework_instance.get_login_info()["user_id"]
    conversation_id: str = data["conversation_id"]

    # 判断消息不是自己发的并且不是群消息时,回复对方
    if sender_user_id != self_user_id and not conversation_id.startswith("R:"):
        wework_instance.send_text(conversation_id=conversation_id, content=f"你发送的消息是: {data['content']}")


try:
    while True:
        pass
except KeyboardInterrupt:
    ntwork.exit_()
    sys.exit()

消息属性

私聊消息属性说明

{
	'appinfo': 'CAQQiZrgsAYYpMv0mZmAgAMgyIKKUw==',
	'at_list': [],
	'content': '我喜欢你',
	'content_type': 0,
	'conversation_id': 'S:1688856625489316_1688856738534700',
	'is_pc': 0,
	'local_id': '34',
	'receiver': '1688856738534700',
	'send_time': '1712852233',
	'sender': '1688856625489316',
	'sender_name': '唤醒手腕',
	'server_id': '1000235'
}

群聊消息属性说明

{
	'appinfo': 'CAQQiKTgsAYYpMv0mZmAgAMg99ak/Ak=',
	'at_list': [],
	'content': '我喜欢你',
	'content_type': 0,
	'conversation_id': 'R:1970325052533916',
	'is_pc': 0,
	'local_id': '41',
	'receiver': '1688856738534700',
	'send_time': '1712853512',
	'sender': '1688856625489316',
	'sender_name': '唤醒手腕',
	'server_id': '1000258'
}

案例:故障离线表格统计

读取故障数据源码

import re

# 假设这是你的消息体字符串
test_message = """  
【故障位置】化州西收费站97车道
【故障情况】不能缴费
【填报人】唤醒手腕
"""


def analysis_repair_data(message):
    # 定义正则表达式模式,用于匹配每个字段
    pattern = r"【故障位置】(.*)\n【故障情况】(.*)\n【填报人】(.*)"

    # 使用re.search来查找匹配项
    match = re.search(pattern, message, re.DOTALL)

    if match:
        fault_location = match.group(1).strip()  # 提取故障位置
        fault_situation = match.group(2).strip()  # 提取故障情况
        reporter = match.group(3).strip()  # 提取填报人

        return {"fault_location": fault_location,
                "fault_situation": fault_situation,
                "reporter": reporter
                }
    else:
        return False

读取维修数据源码

import re

# 假设这是你的消息体字符串
test_message = """  
【故障编号】 
【维修情况】已修复  
【维修人】xxx  
"""


def analysis_solve_data(message):
    # 定义正则表达式模式,用于匹配每个字段
    pattern = r"""  
    【故障编号】(.*)  
    【维修情况】(.*)  
    【维修人】(.*)  
    """
    pattern = re.compile(pattern, re.DOTALL | re.VERBOSE)

    # 使用re.search来查找匹配项
    match = pattern.search(message)

    if match:
        serial = match.group(1).strip()  # 提取故障编号
        repair_situation = match.group(2).strip()  # 提取维修情况
        repair_person = match.group(3).strip()  # 提取维修人
        return {"serial": serial,
                "repair_situation": repair_situation,
                "repair_person": repair_person
                }
    else:
        return False

更新离线 Excel 表格源码

from datetime import datetime

from openpyxl.reader.excel import load_workbook

# 加载工作簿
wb = load_workbook(filename='故障维修登记表.xlsx')
# 选择活动工作表或者通过名字选择工作表
ws = wb.active  # 使用活动工作表


def insert_new_note(repair_data):
    # 获取行数
    row_count = ws.max_row
    now = datetime.now()
    # 使用f-string格式化时间
    formatted_time = f"{now:%Y%m%d-%H%M%S}"
    data = {
        "index": row_count,
        "serial": formatted_time,
        "fault_location": repair_data['fault_location'],
        "fault_situation": repair_data['fault_situation'],
        "reporter": repair_data['reporter'],
        "repair_situation": "",
        "repair_person": ""
    }
    row_num = row_count + 1
    ws.cell(row=row_num, column=1).value = data['index']
    ws.cell(row=row_num, column=2).value = data['serial']
    ws.cell(row=row_num, column=3).value = data['fault_location']
    ws.cell(row=row_num, column=4).value = data['fault_situation']
    ws.cell(row=row_num, column=5).value = data['reporter']
    ws.cell(row=row_num, column=6).value = data['repair_situation']
    ws.cell(row=row_num, column=7).value = data['repair_person']

    # 保存工作簿到文件
    wb.save("故障维修登记表.xlsx")
    return data['serial']


def finish_old_note(solve_data):
    target_name = solve_data['serial']
    # 遍历所有行,查找目标值
    state = False
    for index, row in enumerate(ws.iter_rows(values_only=True)):
        if row[1] == "编号":
            continue
        if row[1] == target_name:  # 假设"Name"在第一列
            # 找到目标行后,修改该行的数据
            # 这里假设我们要修改的是第二列的数据,将其改为"New Value"
            ws.cell(row=(index + 1), column=6).value = solve_data['repair_situation']
            ws.cell(row=(index + 1), column=7).value = solve_data['repair_person']
            state = True
            wb.save("故障维修登记表.xlsx")
            break  # 找到后就退出循环
    if state:
        return solve_data['serial']
    else:
        return False

主程序 app.py 源码

# -*- coding: utf-8 -*-
import sys
from datetime import datetime

import ntwork

from read_repair_data import analysis_repair_data
from read_solve_data import analysis_solve_data
from update_excel import insert_new_note, finish_old_note

wework = ntwork.WeWork()

# 打开 pc 企业微信, smart: 是否管理已经登录的微信
wework.open(smart=True)


# 注册消息回调
@wework.msg_register(ntwork.MT_RECV_TEXT_MSG)
def on_recv_text_msg(wework_instance: ntwork.WeWork, message):
    data = message["data"]

    if data['content'][0:1] != "【":
        return

    sender_user_id = data["sender"]
    self_user_id = wework_instance.get_login_info()["user_id"]
    conversation_id: str = data["conversation_id"]

    # 判断消息不是自己发的并且不是群消息时,回复对方
    if sender_user_id != self_user_id and conversation_id.startswith("R:"):
        insert_data = analysis_repair_data(data['content'])
        if insert_data:
            serial = insert_new_note(insert_data)
            now = datetime.now()
            # 使用f-string格式化时间
            formatted_time = f"{now:%Y-%m-%d %H:%M:%S}"
            print(f"【反馈结果】【{formatted_time}】请注意存在新的反馈:{serial}")
            wework_instance.send_text(conversation_id=conversation_id, content=f"【反馈结果】反馈成功\n【故障编号】{serial}")
        insert_data = analysis_solve_data(data['content'])
        if insert_data:
            serial = finish_old_note(insert_data)
            if serial:
                # 使用f-string格式化时间
                now = datetime.now()
                formatted_time = f"{now:%Y-%m-%d %H:%M:%S}"
                print(f"【维修结果】【{formatted_time}】请注意存在新的维修:{serial}")
                wework_instance.send_text(conversation_id=conversation_id, content=f"【维修结果】维修成功\n【故障编号】{str(serial)}")
            else:
                wework_instance.send_text(conversation_id=conversation_id, content=f"【操作警告】故障编号不存在!")


try:
    while True:
        pass
except KeyboardInterrupt:
    ntwork.exit_()
    sys.exit()

填报故障真机演示

在这里插入图片描述

维修故障真机演示

在这里插入图片描述

Excel 表格情况预览

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1662168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无列名注入

在进行sql注入时,一般都是使用 information_schema 库来获取表名与列名,因此有一种场景是传入参数时会将 information_schema 过滤 在这种情况下,由于 information_schema 无法使用,我们无法获取表名与列名。 表名获取方式 Inn…

使用chatglm3本地部署形成的api给上一篇得到的网页信息text_content做内容提取

使用chatglm3本地部署形成的api给上一篇得到的网页信息text_content做内容提取, chatglm3的api调用见:chatglm3的api调用_启动chatglm3的api服务报错-CSDN博客 import os from openai import OpenAIbase_url "http://localhost:5000/v1/" c…

书生作业:XTuner

作业链接: https://github.com/InternLM/Tutorial/blob/camp2/xtuner/homework.md xtuner: https://github.com/InternLM/xtuner 环境配置 首先,按照xtuner的指令依次完成conda环境安装,以及xtuner库的安装。 然后,我们开始尝试…

基于Vant UI的微信小程序开发(随时更新的写手)

基于Vant UI的微信小程序开发✨ (一)悬浮浮动1、效果图:只要无脑引用样式就可以了2、页面代码3、js代码4、样式代码 (二)底部跳转1、效果图:点击我要发布跳转到发布的页面2、js代码3、页面代码4、app.json代…

STM32CubeMX软件使用(超详细)

1、Cube启动页介绍 2、芯片选择页面介绍 3、输入自己的芯片型号,这里以STM32U575RIT6举例 4、芯片配置页码介绍 5、芯片外设配置栏详细说明 6、点击ClockConfiguration进行时钟树的配置,选择时钟树后可以选择自己想使用的时钟源,也可以直接输…

LeetCode题练习与总结:反转链表Ⅱ--92

一、题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#…

e 值的故事:从复利到自然增长的数学之旅

自然对数函数的底数 e&#xff08;也称为自然常数或欧拉数&#xff09;与 π 一样&#xff0c;是数学中最伟大的常数之一。它大约为 2.718281828&#xff0c;是一个无理数&#xff0c;意味着它的小数部分无限且不重复。 与 π 和 √2 这些由几何发现而来的常数不同&#xff0c…

【高阶数据结构】图 -- 详解

一、图的基本概念 图 是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E)。其中&#xff1a; 顶点集合 V {x | x属于某个数据对象集} 是有穷非空集合&#xff1b; E {(x,y) | x,y属于V} 或者 E {<x, y> | x,y属于V && Path(x, y…

解决常见的Android问题

常见问题&#xff1a; 1、查杀&#xff1a; 查杀一般分为两个方向一种是内存不足的查杀&#xff0c;一种的是因为温度限频查杀&#xff0c;统称为内存查杀&#xff0c;两个问题的分析思路不同 1、内存不足查杀&#xff1a; 主要是因为当用户出现后台运行多个APP或者是相机等…

LeetCode96:不同的二叉搜索树

题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 代码 /*dp[i]&#xff1a;表示i个节点有dp[i]个不同的二搜索叉树递推公式&#xff1a;dp[i] dp[j-1] * dp[i-j], j…

【JavaSE】/*运算符—快速总结*/

目录 前言 一、什么是运算符 二、算术运算符 三、增量运算符 四、自增/自减运算符 五、关系运算符 六、逻辑运算符 七、位运算符 八、移位运算符 九、条件运算符 十、运算符的优先级 前言 Java 中的运算符和 C语言 的运算符规则有很多类型的地方&#xff0c;我们只…

K8s源码分析(二)-K8s调度队列介绍

本文首发在个人博客上&#xff0c;欢迎来踩&#xff01; 本次分析参考的K8s版本是 文章目录 调度队列简介调度队列源代码分析队列初始化QueuedPodInfo元素介绍ActiveQ源代码介绍UnschedulableQ源代码介绍**BackoffQ**源代码介绍队列弹出待调度的Pod队列增加新的待调度的Podpod调…

LinkedList链表

LinkedList 的全面说明 LinkList底层实现了双向链表和双端队列特点可以添加任意元素&#xff08;元素可以重复&#xff09;&#xff0c;包括null线程不安全&#xff0c;没有实现同步 LinkedList 的底层操作机制 LinkedList底层维护了一个双向链表LinkList中维护了两个属性fi…

【C#进阶】简单数据结构类

简单数据结构类 文章目录 1、Arraylist1、ArrayList的本质2、声明3、增删查改4、装箱拆箱思考 背包售卖 2、Stack1、Stack的本质2、声明3、增取查改4、遍历思考 计算一个数的二进制 3、Queue1、Queue的本质2、声明3、增取查改4、遍历思考 每隔一段时间打印一条消息 4、Hashtab…

运营商的mpls专线

在当今高速发展的数字化时代&#xff0c;网络已成为企业发展不可或缺的基础设施。作为企业网络 连接的重要组成部分&#xff0c;MPLS专线在运营商的推动下逐渐成为了企业选择的首选。 MPLS&#xff08;Multi-Protocol Label Switching&#xff09;是一种基于标签的交换技术&am…

QT C++(QWidget类及其常见的属性)

文章目录 1. QWidget类及其常见的属性 1. QWidget类及其常见的属性 QT各种控件都是继承自QWidget类&#xff0c;QWidget类是QT控件体系中通用的部分。 QWidget属性如下图 常见的QT属性为&#xff1a; enabled&#xff1a;描述控件是否处于可用状态&#xff08;禁用状态这个…

ssrf学习2——内网ip绕过

环回地址绕过 尝试访问内网 也就是127.0.0.1里面的flag.php 但是如果真的去访问127.0.0.1/flag.php 还是不行 也就是说127.0.0.1被过滤了 进制转换 127.0.0.1是点分十进制 可以用二进制八进制十六进制来绕过过滤 0x7F000001/flag.php 017700000001/flag.php(八进制前面是…

Yolov8目标检测——在Android上部署Yolov8 tflite模型

1. 简介 YOLOv8 是一种用于目标检测的深度学习模型&#xff0c;它是 YOLO&#xff08;You Only Look Once&#xff09;系列的最新版本之一。YOLO 系列因其高效和准确性而在计算机视觉领域非常受欢迎&#xff0c;特别是在需要实时目标检测的应用中&#xff0c;如视频监控、自动…

docker搭建mysql集群实现主从复制

前言 随着业务的增长&#xff0c;一台数据服务器已经满足不了需求了&#xff0c;负载过重。这个时候就需要减压了&#xff0c;实现负载均衡和读写分离&#xff0c;一主一丛或一主多从。 主服务器只负责写&#xff0c;而从服务器只负责读&#xff0c;从而提高了效率减轻压力。 …

docker安装nginx支持ssl 实现https访问(完整版)

全文目录,一步到位 1.前言简介1.1 专栏传送门1.1.1 本文简介 2. docker安装nginx支持ssl2.0 准备ssl证书(例: 阿里云)2.0.1 配置域名解析2.0.2 找到数字证书管理服务并签发ssl证书2.0.3 选择默认证书 填写域名 创建2.0.4 提交审核, 签发成功2.0.5 解压并上传到宿主机ssl路径下 …