关于python脚本执行推送的另一条路(非server酱)

, Read in about 3 min

Posted by Ryen on Tuesday, April 6, 2021
With final update in December 26,2023

本文总阅读量

一.失去无限制的免费推送

因为微信发布公告将在4月底下线模板消息,Server酱开发了以企业微信为主的多通道新版( Turbo版 sct.ftqq.com ),旧版将在4月后下线。

Server酱作为一项免费提供的基础推送服务,支撑着每月超过 5000 万次的访问。这背后,是不小的资源、维护成本。

以下为最新server酱费用情况:

  • 8.00 12.00会员 1个月
  • 39.00 144.00会员 12个月
  • 180.00 720.00会员 60个月

**注:**摸着良心说话(这么多项目白嫖了这么久收点费也正常,而且一年真的不贵,随便一台服务器也不止这个价吧),有经济实力一定要支持!

「捐赠会员」的功能说明

试用捐赠会员
资格获得方式注册即可获得捐赠获得
每天最多发送条数5不限制,但 API 请求次数上限为 1000
群发不支持可通过 openid 参数抄送多人
卡片内容显示仅显示标题显示标题和内容
每天 API 最大请求次数10001000,此限制主要防止程序出错
每分钟最多发送条数55,此限制主要防止程序出错
推送内容保留时间1天7天
转发消息到企业微信支持支持
转发消息到钉钉支持支持
转发消息到飞书支持支持

二.利用企业微信机器人

其实企业微信本身就支持机器人,可以使用API发送文本、图片、音频、视频、文件等消息,实现在个人微信中接收消息,无需下载企业微信客户端。

1.注册企业微信:用电脑打开企业微信官网,注册一个企业,企业微信目前是支持个人注册的,即使没有企业,还是可以使用。前往 https://work.weixin.qq.com/ 使用个人微信注册企业微信。

2.进入管理后台,我的企业 > 企业信息,可以看到企业ID。推送UID直接填 @all ,推送给公司全员。

3.创建机器人,得到AgentId和Secret注册成功后,点「管理企业」进入管理界面,选择「应用管理」 → 「自建」 → 「创建应用」

4.我的企业 > 微信插件 > 邀请关注,用个人微信扫码关注,即可使用个人微信接收消息。

三.python代码

以下代码能直接运行(已测试,已修改)

如果需要加入到已部署的云函数或者github actions中需要自己修改

功能:

  • 推送文本
  • 推送文章(板块样式)
  • 推送图片
  • 推送音频
  • 推送视频
  • 推送文件(.zip .docx .pdf .exe 等常见文件格式)

python:

import requests
import json


class wechatbot:
    '''
    企业微信机器人
    '''

    def __init__(self, corpid, agentid, secret):
        '''
        corpid: 企业ID
        agentid: 机器人的AgentId
        secret: 机器人的Secret
        '''
        self.corpid = corpid
        self.agentid = agentid
        self.secret = secret

    def get_access_token(self):
        get_token_api = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={self.secret}'
        r = requests.get(get_token_api).json()
        print(r)
        if r["errcode"] == 0:
            self.access_token = r["access_token"]

    def upload_file(self, file_type, file_path, file_name):
        upload_api = f'https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={self.access_token}&type={file_type}'
        files = {'media': (file_name, open(file_path, "rb"), '', {})}

        # headers = {'Content-Type': 'multipart/form-data'}
        r = requests.post(upload_api,  files=files).json()
        print(r)
        if r["errcode"] == 0:
            return r["media_id"]

    def send(self, msgtype, content):
        send_message_api = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={self.access_token}'

        message = {
            "agentid": self.agentid,
            "touser": "@all",
            "msgtype": msgtype,
            msgtype: content
        }

        headers = {'Content-Type': 'application/json'}
        r = requests.post(send_message_api, data=json.dumps(message),
                          headers=headers).json()
        print(r)
        return r["errcode"]


if __name__ == "__main__":
    corpid = 'wxxxxxxxxxxxxxxxxx'
    agentid = 1000002
    secret = 'SCXXXXXXXXXXXXXXXXXXXXXXXXXX'

    bot = wechatbot(corpid, agentid, secret)
    bot.get_access_token()
    #bot.access_token = '4awAnq'

    text = {
        "content": 'test - send from vscode'
    }

    news = {
        "articles": [
            {
                "title": "article 1",
                "description": "description 1",
                "url": "https://www.example.com",
                "picurl": "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
            },
            {
                "title": "article 2",
                "description": "description 2",
                "url": "https://www.example.com",
                "picurl": "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
            }
        ]
    }

    image_id = bot.upload_file('image', './test/src/123+123.png', '123+123.png')
    # image_id = '3Ru536yMS8NKoZ5lC5QBB3GyHktVWEAy8yuEoyJhXXXX'
    image = {
        "media_id": image_id
    }

    voice_id = bot.upload_file('voice', './test/src/hello.amr', 'hello.amr')
    # voice_id = '3XOId6MOk_gW1X48x0L0ZXfhHclK72DzUe1ZL-R1XXXX'
    voice = {
        "media_id": voice_id
    }

    video_id = bot.upload_file('video', './test/src/test_video.mp4', 'video.mp4')
    # video_id = '37NqJGlKZU3vcvijSO1XoJwmJ9kfyt4Pw3hhG4w2HvbkoVMPco_38BVOg9F0LXXXX'
    video = {
        "media_id": video_id,
        "title": "Title",
        "description": "Description"
    }

    file_id = bot.upload_file('file', './test/test.pdf', 'test.pdf')
    # file_id = '3MAsA-EWw0g1iAhlWghUzbHOUp_n_nS1iLYS1uEzXXXX'
    f = {
        "media_id": file_id
    }

    textcard = {
        "title": "通知",
        "description": '''
            <div class=\"gray\">gray</div>
            <div class=\"normal\">normal</div>
            <div class=\"highlight\">highlight</div>''',
        "url": "https://www.example.com",
        "btntxt": "More"
    }

    markdown = {
        "content": """# Title
            `code`
            **bold**
            > <font color=\"info\">info</font>
            <font color=\"warning\">warning</font>
            <font color=\"comment\">comment</font>
            [link](https://www.example.com)
            """
    }

    taskcard = {
        "title": "Title",
        "description": "Description<br>description",
        "url": "https://www.example.com",
        "task_id": "taskid002",
        "btn": [
            {
                "key": "key1",
                "name": "name1",
                "replace_name": "replace_name1",
                "color": "red",
                "is_bold": True
            },
            {
                "key": "key2",
                "name": "name2",
                "replace_name": "replace_name2"
            }
        ]
    }

    bot.send("text", text)
    bot.send("news", news)
    bot.send("image", image)
    bot.send("voice", voice)
    bot.send("video", video)
    bot.send("file", f)
    bot.send("textcard", textcard)
    # bot.send("markdown", markdown) # 个人微信不支持
    # bot.send("taskcard", taskcard) # 个人微信不支持
    
  1. 根据企业ID、机器人的AgentId和Secret获取access_token
  2. 调用发送消息API发送指定格式的数据
  3. 文本型消息可以直接发送,各种文件需要先上传获取media_id
  4. access_token的有效期一般为2小时,media_id的有效期是3天

「真诚赞赏,手留余香」

Ryen's Blog

真诚赞赏,手留余香

使用微信扫描二维码完成支付