Wechat_Sender¶
随时随地发送消息到微信
初衷¶
wxpy 基于 itchat 提供了较为完备的微信个人号 API ,而我想使用个人微信来接收我的网站的报警信息以及一些爬虫的结果,因此我写了这个工具。
安装¶
pip install wechat_sender
运行环境¶
Python 2.7 及以上 Python 3 及以上
使用¶
- 登录微信并启动 wechat_sender 服务.
from wxpy import *
from wechat_sender import *
bot = Bot()
listen(bot)
# 之后 wechat_sender 将持续运行等待接收外部消息
- 在外部向微信发送消息.
from wechat_sender import Sender
Sender().send('Hello From Wechat Sender')
# Hello From Wechat Sender 这条消息将通过 1 中登录微信的文件助手发送给你
如果你是 wxpy 的使用者,只需更改一句即可使用 wechat_sender:
例如这是你本来的代码:
# coding: utf-8
from __future__ import unicode_literals
from wxpy import *
bot = Bot('bot.pkl')
my_friend = bot.friends().search('xxx')[0]
my_friend.send('Hello WeChat!')
@bot.register(Friend)
def reply_test(msg):
msg.reply('test')
bot.join()
使用 wechat_sender:
# coding: utf-8
from __future__ import unicode_literals
from wxpy import *
from wechat_sender import listen
bot = Bot('bot.pkl')
my_friend = bot.friends().search('xxx')[0]
my_friend.send('Hello WeChat!')
@bot.register(Friend)
def reply_test(msg):
msg.reply('test')
listen(bot) # 只需改变最后一行代码
之后如果你想在其他程序或脚本中向微信发消息,只需要:
# coding: utf-8
from wechat_sender import Sender
Sender().send("Hello From Wechat Sender")
交流¶
扫描二维码,验证信息输入 ‘wechat_sender’ 或 ‘加群’ 进入微信交流群
listen 方法¶
listen() 方法用于监听 wxpy 的 bot 对象实例并启动 wechat_sender 服务,为外部发送消息到微信提供支持。
-
wechat_sender.
listen
(bot, receivers=None, token=None, port=10245, status_report=False, status_receiver=None, status_interval=3600000)[源代码]¶ 传入 bot 实例并启动 wechat_sender 服务
参数: - bot – (必填|Bot对象) - wxpy 的 Bot 对象实例
- receivers – (选填|wxpy.Chat 对象|Chat 对象列表) - 消息接收者,wxpy 的 Chat 对象实例, 或 Chat 对象列表,如果为 list 第一个 Chat 为默认接收者。如果为 Chat 对象,则默认接收者也是此对象。 不填为当前 bot 对象的文件接收者
- token – (选填|str) - 信令,防止 receiver 被非法滥用,建议加上 token 防止非法使用,如果使用 token 请在初始化 Sender() 时也使用统一 token,否则无法发送。token 建议为 32 位及以上的无规律字符串
- port – (选填|int) - 监听端口, 监听端口默认为 10245 ,如有冲突或特殊需要请自行指定,需要和 Sender() 统一
- status_report – (选填|bool) - 是否开启状态报告,如果开启,wechat_sender 将会定时发送状态信息到 status_receiver
- status_receiver – (选填|Chat 对象) - 指定 status_receiver,不填将会发送状态消息给默认接收者
- status_interval – (选填|int|datetime.timedelta) - 指定状态报告发送间隔时间,为 integer 时代表毫秒
小技巧
指定接收者¶
from wxpy import *
from wechat_sender import listen
# 这里登录单独申请的微信号
bot = Bot()
# 这里查询你的个人微信, search 填入你的微信昵称
my = bot.friends().search('your name')[0]
# 传入你的私人微信作为接收者
listen(bot, receivers=my)
向你的私人微信发送消息:
from wechat_sender import Sender
Sender().send('hello')
指定多个接收者¶
from wxpy import *
from wechat_sender import listen
# 这里登录单独申请的微信号
bot = Bot()
# 这里查询你的个人微信, search 填入你的微信昵称
my = bot.friends().search('your name')[0]
group = bot.groups().search('group name')[0]
# 传入接收者列表
listen(bot, receivers=[my, group])
向 group 发送消息:
from wechat_sender import Sender
Sender('group name').send('hello')
使用 token 以防 sender 被滥用¶
警告
wechat_sender 基于 http 服务提供消息发送服务,如果部署在服务器上有潜在盗用风险,所以 listen()
初始化时务必传入 token 以防止盗用
警告
注意保证 token 安全,不要被泄漏
# 同样,基于 http 的服务需要一个端口与外部通信,listen 默认端口是 10245 ,你可以改成任何空闲端口,例如 8888
listen(bot, receiver, token='your secret', port=8888)
注解
如果传入了 token 或 port 请务必保证 Sender
在初始化时也传入相同的 token 和 port
开启 wechat_sender 的状态报告¶
鉴于微信个人号接口的不稳定性,我们可以开启 wechat_sender 的状态报告,定时向 status_receiver 发送状态信息
listen(bot, my, token='your secret', status_report=True, status_receiver=my)
注解
Sender 发送者对象¶
Sender 对象可以理解为在外部程序中( 非 wechat_sender 服务,例如你的个人脚本、网站等 )向微信发送消息的发送者
-
class
wechat_sender.
Sender
(token=None, receivers=None, host=u'http://localhost', port=10245)[源代码]¶ sender 对象,任何外部程序向微信发送消息都需要初始化 sender 对象:
from wechat_sender import Sender sender = Sender(token='test', receiver='wechat_name,xxx,xxx') # 向 receiver 发送消息 sender.send('Hello From Wechat Sender')
-
Sender.
__init__
(token=None, receivers=None, host=u'http://localhost', port=10245)[源代码]¶ 参数: - token – (选填|str) - 信令,如果不为空请保持和 listen 中的 token 一致
- receivers – (选填|str) - 接收者,wxpy 的 puid 或 微信名、昵称等,多个发送者请使用半角逗号 ‘,’ 分隔。不填将发送至 default_receiver
- host – (选填|str) - 远程地址,本地调用不用填写
- port – (选填|int) - 发送端口,默认 10245 端口,如不为空请保持和 listen 中的 port 一致
指定多个发送者
Sender 的 receiver 可以指定多个发送者,由这个 Sender 发送的消息默认会广播给多个发送者:
# coding: utf-8
import datetime
from wechat_sender import Sender
sender = Sender(token='xxx', receivers='aaa,bbb,ccc,ddd')
sender.send('broadcast message')
注解
使用英文半角逗号分隔多个接收者
-
Sender.
send
(message)[源代码]¶ 发送基本文字消息
参数: message – (必填|str) - 需要发送的文本消息 返回: - status:发送状态,True 发送成,False 发送失败
- message:发送失败详情
-
Sender.
delay_send
(content, time, title=u'', remind=3600)[源代码]¶ 发送延时消息
参数: - content – (必填|str) - 需要发送的消息内容
- time – (必填|str|datetime) - 发送消息的开始时间,支持 datetime.date、datetime.datetime 格式或者如 ‘2017-05-21 10:00:00’ 的字符串
- title – (选填|str) - 需要发送的消息标题
- remind – (选填|int|datetime.timedelta) - 消息提醒时移,默认 1 小时,即早于 time 值 1 小时发送消息提醒, 支持 integer(毫秒) 或 datetime.timedelta
返回: - status:发送状态,True 发送成,False 发送失败
- message:发送失败详情
发送延时消息
某些情况下,我们希望消息可以延迟发送,例如日程、会议提醒等,这时用 Sender.delay_send()
即可满足需求:
# coding: utf-8
import datetime
from wechat_sender import Sender
sender = Sender()
time = datetime.datetime.now()+datetime.timedelta(hours=1)
sender.delay_send(content="测试内容", time=time, title="测试标题", remind=datetime.timedelta(minutes=59))
如果返回正常,1 分钟后你将收到这条消息时间是 1 小时后的消息提醒:
#标题:测试标题
#时间:2017-06-07 12:56:16
#内容:延迟消息测试
-
Sender.
periodic_send
(content, interval, title=u'')[源代码]¶ 发送周期消息
参数: - content – (必填|str) - 需要发送的消息内容
- interval – (必填|int|datetime.timedelta) - 发送消息间隔时间,支持 datetime.timedelta 或 integer 表示的秒数
- title – (选填|str) - 需要发送的消息标题
返回: - status:发送状态,True 发送成,False 发送失败
- message:发送失败详情
发送周期消息
如果希望某条消息周期性发送到微信,可以使用 Sender.periodic_send()
:
# coding: utf-8
import datetime
from wechat_sender import Sender
sender = Sender()
interval = datetime.timedelta(seconds=10)
sender.periodic_send(content='测试消息', interval=interval, title='测试标题')
如果返回正常,每隔 10 s 你将收到一条消息如下:
# 标题:测试标题
# 内容:周期消息测试test
小技巧
使用 Wechat Sender 的控制命令 查看已注册的延时周期消息
-
Sender.
send_to
(content, search)[源代码]¶ 向指定好友发送消息
参数: - content – (必填|str) - 需要发送的消息内容
- search – (必填|str|dict|list)-搜索对象,同 wxpy.chats.search 使用方法一样。例如,可以使用字符串进行搜索好友或群,或指定具体属性搜索,如 puid=xxx 的字典
返回: - status:发送状态,True 发送成,False 发送失败
- message:发送失败详情
发送定向消息
如果你希望某条消息发送给指定的微信好友,你可以使用 Sender.send_to()
:
# coding: utf-8
import datetime
from wechat_sender import Sender
sender = Sender()
sender.send_to('Hello From Wechat Sender', '微信好友昵称')
如果返回正常,你指定的微信好友将收到这条消息
小技巧
Sender.send_to()
的 search 参数使用方法和 wxpy 的 wxpy.chats().search(). 一致使用多条件查询好友:
# coding: utf-8
import datetime
from wechat_sender import Sender
sender = Sender()
sender.send_to('Hello From Wechat Sender', search={'city': 'xx', 'nick_name': 'xxx'})
Sender 日志对象¶
Sender 日志对象可以更平滑的接入外部应用的 log 系统中,基本无需更改代码即可使应用日志发送到微信
-
class
wechat_sender.
LoggingSenderHandler
(name=None, token=None, receiver=None, host=u'http://localhost', port=10245, level=30)[源代码]¶ wechat_sender 的 LoggingHandler 对象,可以使用 logging.addHandler() 的方式快速使外部应用支持微信日志输出。在外部应用中:
# spider.py # 假如在一个爬虫脚本,我们想让此脚本的警告信息直接发到微信 import logging from wechat_sender import LoggingSenderHandler logger = logging.getLogger(__name__) # spider code here def test_spider(): ... logger.exception("EXCEPTION: XXX") def init_logger(): sender_logger = LoggingSenderHandler('spider', level=logging.EXCEPTION) logger.addHandler(sender_logger) if __name__ == '__main__': init_logger() test_spider()
-
LoggingSenderHandler.
__init__
(name=None, token=None, receiver=None, host=u'http://localhost', port=10245, level=30)[源代码]¶ 参数: - name – (选填|str) - 标识日志来源,不填将取应用所在服务器地址为名称
- token – (选填|str) - 信令,如果不为空请保持和 listen 中的 token 一致
- receiver – (选填|str) - 接收者,wxpy 的 puid 或 微信名、昵称等,不填将发送至 default_receiver
- host – (选填|str) - 远程地址,本地调用不用填写
- port – (选填|int) - 发送端口,默认 10245 端口,如不为空请保持和 listen 中的 port 一致
- level – (选填|int) - 日志输出等级,默认为 logging.WARNING
Wechat Sender 的控制命令¶
我们向 wechat_sender 发送支持的命令来获取 wechat_sender 的信息
注解
wechat_sender 只会响应 default_recevier 的命令
注解
listen()
传入 receivers 时会把第一个 receiver 当做 default_recevierSender
都将把消息发给默认接收者Wechat Sender 中的基本类¶
-
class
wechat_sender.objects.
WxBot
(bot=None, receivers=None, status_receiver=None, *args, **kwargs)[源代码]¶ 储存微信 bot 相关信息及 wechat_sender 各类 receiver 的类
-
WxBot.
__init__
(bot=None, receivers=None, status_receiver=None, *args, **kwargs)[源代码]¶ 参数: - bot – wxpy bot 对象实例
- receivers – wxpy chat 对象实例
- status_receiver – wxpy chat 对象实例
-
class
wechat_sender.objects.
Message
(content, title=None, time=None, remind=None, interval=None, receivers=None)[源代码]¶ wechat_sender 消息类,是所有 wechat_sender 发送消息的基本类型
最佳实践¶
在服务器 XXX.XXX.XXX.XXX 部署 wechat_sender 服务:
from wxpy import *
from wechat_sender import *
bot = Bot('bot.pkl', console_qr=True)
bot.enable_puid()
master = ensure_one(bot.friends().search(puid='xxxx'))
log_group = ensure_one(bot.groups().search(puid='xxxxxx'))
other = ensure_one(bot.friends().search('xxxxxx'))
token = 'xxxxxxxxxxxxxxxxxxxxx'
listen(bot, [master, other, log_group], token=token, port=9090, status_report=True, status_receiver=log_group)
在其他地方进行消息发送:
from wechat_sender import Sender
host = 'XXX.XXX.XXX.XXX'
token = 'xxxxxxxxxxxxxxxxxxxxx'
sender = Sender(token=token, receiver='xxx', host=host, port='9090')
在其他应用中加入 wechat_sender logging handler:
# 假如这是你另一台服务器上的脚本
# spider.py
import logging
from wechat_sender import LoggingSenderHandler
logger = logging.getLogger(__name__)
# spider code here
def test_spider():
...
logger.exception("EXCEPTION: XXX")
def init_logger():
token = 'xxxxxxxxxxxxxxxxxxxxx'
sender_logger = LoggingSenderHandler('spider', token=token, port=9090, host='XXX.XXX.XXX.XXX', receiver='xxx', level=logging.EXCEPTION)
logger.addHandler(sender_logger)
if __name__ == '__main__':
init_logger()
test_spider()
只需要在原有 logger 中加入 wechat_sender 的 log handler 即可实现把日志发送到微信
底层 API¶
listen()
中设定的 port 与 wechat_sender 部署地址即为服务地址,默认: http://localhost:10245
ADDR = http://localhost:10245
返回码说明¶
status结果码 | 状态 |
---|---|
0 | 成功 |
1 | 权限不足(token 不正确) |
2 | bot 故障 |
3 | wechat_sender 服务故障 |
4 | 未知错误 |
发送普通消息¶
POST ADDR/message
参数¶
content: | (必填|str) - 需要发送的消息 |
---|---|
token: | (选填|str) - 令牌 |
receiver: | (选填|str) - 接收者名称 |
返回¶
{
"status": 1,
"message": "Token is missing"
}
or
{
"status": 0,
"message": "Success"
}
发送延时消息¶
POST ADDR/delay_message
参数¶
content: | (必填|str) - 需要发送的消息 |
---|---|
title: | (选填|str) - 消息标题 |
time: | (选填|str) - 消息时间, “XXXX-XX-XX XX:XX:XX” 形式 |
remind: | (选填|int) - 提醒时移,integer 表示的秒 |
token: | (选填|str) - 令牌 |
receiver: | (选填|str) - 接收者名称 |
返回¶
{
"status": 1,
"message": "Token is missing"
}
or
{
"status": 0,
"message": "Success"
}