Python自动化飞书机器人:图文消息推送实战指南

发布时间:2026/7/30 23:12:30

Python自动化飞书机器人:图文消息推送实战指南 1. 项目概述为什么需要自动化推送图文消息在企业日常运营中信息的高效、准确触达是提升团队协作效率的关键。想象一下每天需要将销售日报、系统监控告警、项目进度更新或者活动宣传海报手动复制粘贴到各个工作群不仅耗时费力还容易出错遗漏。飞书作为一款集成了IM、日历、文档、云盘的协同办公平台其开放的机器人接口为我们提供了自动化解决方案。这个项目的核心就是利用Python脚本扮演一个“不知疲倦的助理”自动将结构化的图文信息发送到指定的飞书群聊。这里的“图文信息”不仅仅是“图片文字”的简单堆砌而是指符合飞书富文本消息格式的、具备良好视觉层次和交互性的消息卡片。这对于发布产品更新日志、数据看板截图、会议纪要摘要等场景尤为实用。无论是运维工程师需要推送服务器状态还是市场人员需要分发每日战报都可以通过这个小小的机器人来解放双手实现信息流转的标准化与自动化。接下来我将以一个完整的、可复现的项目为例拆解从零开始搭建一个飞书图文消息机器人的全过程涵盖思路设计、代码实现、安全配置到避坑指南的所有细节。2. 核心思路与飞书机器人机制解析在动手写代码之前我们必须先理解飞书机器人的工作模式。飞书开放平台为机器人提供了两种主要的消息发送方式Webhook和应用授权。对于大多数主动推送场景我们使用Webhook就足够了它更轻量、更简单。2.1 方案选型为什么首选WebhookWebhook的本质是一个由飞书平台提供的唯一URL。当你向这个URL发送一个符合格式的HTTP POST请求时飞书服务器就会接收请求内容并将其转换为一条消息投递到对应的群聊中。这就像是你知道了某个邮箱的地址只要按格式写好信寄过去对方就能收到。相比于需要处理OAuth2.0授权、获取tenant_access_token的应用授权方式Webhook方案有三大优势零依赖无需维护access_token的生命周期通常2小时失效避免了定时刷新令牌的逻辑。权限清晰一个Webhook URL只对应一个群聊权限隔离性好不会误发到其他群。简单可靠逻辑简单就是构造HTTP请求非常适合定时任务或事件触发型的消息推送。因此除非你的机器人需要主动读取群消息、获取群成员列表等更复杂的交互否则Webhook是发送图文信息的首选。2.2 图文消息的载体认识“消息卡片”飞书的消息类型有很多如纯文本、图片、富文本、群名片等。但要发送“图文信息”我们主要使用“消息卡片”。这是一种高度可定制的消息格式通过JSON结构来定义消息的视觉布局和内容。一个典型的图文消息卡片包含以下元素header卡片标题通常用于显示消息主题。elements卡片内容主体一个数组可以包含多个内容模块。config卡片的全局配置如是否启用消息更新。在elements中我们可以通过不同的“标签”来组合图文markdown用于渲染富文本支持加粗、列表、链接等是放置说明文字、数据摘要的理想选择。img用于插入图片。这里有一个关键点飞书消息卡片不支持直接通过互联网URL显示图片出于安全考虑。图片必须先上传到飞书服务器获得一个飞书内部的image_key后才能使用。div分割线用于区分不同内容区块。note注释模块通常用于放置次要提示信息。理解了这个结构我们就知道编程任务有两部分1. 上传图片获取image_key2. 组装包含markdown和img模块的卡片JSON并通过Webhook发送。3. 实操准备创建机器人与获取关键凭证理论清晰后我们进入实操环节。第一步是在飞书开放平台上配置好我们的机器人。3.1 创建自定义机器人打开飞书进入你需要推送消息的目标群聊。点击群聊右上角的···选择“设置”。在设置页面找到“群机器人”选项并点击。选择“添加机器人”-“自定义机器人”。填写机器人信息机器人名字例如“数据播报助手”。机器人描述选填说明机器人的用途。安全设置这是重中之重务必至少选择一种安全验证方式。强烈推荐使用“签名校验”。系统会生成一个Signing Key请立即复制保存。后续我们的每一次请求都需要用这个密钥生成签名飞书服务器会据此验证请求的合法性防止他人恶意调用你的Webhook。注意Signing Key和接下来的Webhook URL一旦关闭弹窗就无法再完整查看只能重置。务必在第一步就妥善保存。创建完成后你将获得一个以https://open.feishu.cn/open-apis/bot/v2/hook/开头的Webhook地址。这个地址就是机器人的“接收邮箱”请同样复制保存。至此你得到了两个核心凭证Webhook URL和Signing Key。3.2 Python环境与依赖库选择本项目对Python环境要求宽松Python 3.6及以上版本均可。我们将使用两个核心库requests用于发送HTTP请求与飞书API交互。httpx(可选但推荐)一个现代、异步能力更强的HTTP客户端。如果后续需要高性能并发发送httpx是更好的选择。本例中以requests为例进行说明。安装命令非常简单pip install requests # 如果选择httpx pip install httpx4. 核心代码实现与分步拆解我们将代码实现分为三个核心函数计算签名、上传图片、发送卡片消息。最后用一个主函数将它们串联起来。4.1 第一步实现签名计算函数飞书要求使用签名校验时每个Webhook请求的Header中必须包含X-Lark-Signature字段其值是对“时间戳”和“签名密钥”进行特定加密后的结果。这是保障安全的关键步骤。import time import hashlib import base64 import hmac def generate_signature(timestamp: str, signing_key: str) - str: 生成飞书机器人Webhook请求所需的签名。 参数: timestamp: 当前时间戳字符串格式秒级。 signing_key: 创建机器人时获得的签名密钥。 返回: 计算得到的签名字符串。 # 将时间戳和密钥用换行符拼接 string_to_sign f{timestamp}\n{signing_key} # 使用HMAC-SHA256算法进行加密 hmac_code hmac.new( string_to_sign.encode(utf-8), digestmodhashlib.sha256 ).digest() # 将加密结果进行Base64编码 sign base64.b64encode(hmac_code).decode(utf-8) return sign关键点解析timestamp必须与请求头中的X-Lark-Request-Timestamp值一致通常取当前时间的秒级时间戳int(time.time())。拼接字符串时中间是\n换行符这个细节不能错。整个计算过程是标准化的任何语言都可以按此流程实现。4.2 第二步实现图片上传函数如前所述发送图文卡片需要飞书内部的image_key。我们需要先将本地或网络的图片文件上传到飞书。import requests def upload_image_to_feishu(image_path: str, app_id: str, app_secret: str) - str: 将图片上传至飞书并获取image_key。 注意此方法需要用到应用的app_id和app_secret适用于更复杂的应用机器人。 对于仅使用Webhook的简单场景更常见的做法是先将图片上传到公司的图床或公网可访问的地址 然后在卡片中使用 markdown 语法 ![alt](url) 来间接显示。 这里为了演示完整的“官方卡片图片”流程仍展示上传API方法。 # 1. 获取 tenant_access_token token_url https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal token_data {app_id: app_id, app_secret: app_secret} token_resp requests.post(token_url, jsontoken_data) token_resp.raise_for_status() access_token token_resp.json()[tenant_access_token] # 2. 上传图片 upload_url https://open.feishu.cn/open-apis/im/v1/images headers {Authorization: fBearer {access_token}} # 判断是本地文件还是网络图片 if image_path.startswith((http://, https://)): # 网络图片先下载到内存 img_response requests.get(image_path) img_response.raise_for_status() files {image: (image.jpg, img_response.content, image/jpeg)} else: # 本地文件 with open(image_path, rb) as f: files {image: (image.jpg, f, image/jpeg)} # 必须设置此请求头表示表单上传 headers[Content-Type] multipart/form-data # 上传类型为“message”表示用于消息卡片 data {image_type: message} upload_resp requests.post(upload_url, headersheaders, filesfiles, datadata) upload_resp.raise_for_status() # 3. 返回 image_key image_key upload_resp.json()[data][image_key] return image_key重要提醒与备选方案 这个函数需要应用的app_id和app_secret这属于“应用机器人”的范畴流程更复杂。对于很多仅需推送的简单场景申请一个正式应用可能过于繁琐。更实用的替代方案是使用“图片链接” 直接在卡片的markdown模块中使用标准的Markdown图片语法![图片描述](图片公网URL)。飞书会自动抓取并预览该链接的图片。这样就不需要上传步骤但前提是你的图片有一个公网可访问的URL例如上传到公司内部的图床系统、阿里云OSS、腾讯云COS等。实操心得对于内部仪表盘截图等动态生成的图片我通常先用selenium或playwright截图保存然后调用内部图床API上传获取URL最后再将URL填入Markdown。这比直接调用飞书上传接口更通用且不受飞书接口频率限制。4.3 第三步组装并发送消息卡片这是最核心的函数负责构造最终的JSON消息体并调用Webhook。import json import time def send_feishu_card_with_webhook(webhook_url: str, signing_key: str, title: str, content_md: str, image_url_or_key: str None, use_image_key: bool False): 通过Webhook发送飞书图文消息卡片。 参数: webhook_url: 机器人的Webhook地址。 signing_key: 机器人的签名密钥。 title: 消息卡片的标题。 content_md: 消息内容的Markdown字符串。 image_url_or_key: 图片的URL用于markdown或飞书image_key用于img元素。 use_image_key: 布尔值指定image_url_or_key是image_key(True)还是图片URL(False)。 # 1. 准备时间戳和签名 timestamp str(int(time.time())) sign generate_signature(timestamp, signing_key) # 2. 构建消息卡片JSON card_elements [] # 添加文字内容模块 if content_md: card_elements.append({ tag: markdown, content: content_md }) # 添加图片模块 if image_url_or_key: if use_image_key: # 方式一使用官方img元素需要image_key card_elements.append({ tag: img, img_key: image_url_or_key, # 这里传入的是image_key alt: { tag: plain_text, content: 相关图片 } }) else: # 方式二在markdown中嵌入图片链接更简单 # 如果之前没有添加内容模块先添加一个 if not card_elements: card_elements.append({tag: markdown, content: }) # 在内容末尾追加图片Markdown语法 # 注意这里简化处理实际可能需要更精细的合并逻辑 card_elements[0][content] f\n\n![相关图片]({image_url_or_key}) # 完整的消息体 message_data { msg_type: interactive, card: { config: { wide_screen_mode: True # 启用宽屏模式显示效果更好 }, header: { title: { tag: plain_text, content: title }, template: blue # 标题栏颜色可选 blue, wathet, turquoise, green, yellow, orange, red, violet, purple, indigo, grey }, elements: card_elements } } # 3. 准备请求头 headers { Content-Type: application/json, X-Lark-Request-Timestamp: timestamp, X-Lark-Signature: sign } # 4. 发送POST请求 response requests.post(webhook_url, headersheaders, datajson.dumps(message_data)) response.raise_for_status() result response.json() if result.get(code) 0 and result.get(msg) success: print(消息发送成功) else: print(f消息发送失败: {result}) raise Exception(f飞书API返回错误: {result})4.4 第四步主函数与示例调用将以上所有部分组合起来形成一个完整的脚本。def main(): # 配置区请替换成你自己的信息 WEBHOOK_URL https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx SIGNING_KEY your_signing_key_here # 示例1发送纯文本Markdown消息 print(正在发送文本消息...) send_feishu_card_with_webhook( webhook_urlWEBHOOK_URL, signing_keySIGNING_KEY, title【系统日报】, content_md**各位同事大家好**\n\n以下是昨日关键数据\n- 销售额¥125,430\n- 新用户注册324人\n- 系统平均响应时间font colorgreen**156ms**/font\n\n详情请查看[数据仪表盘](https://bi.your-company.com)。 ) # 示例2发送包含网络图片链接的消息推荐简易方案 print(\n正在发送带网络图片的消息...) send_feishu_card_with_webhook( webhook_urlWEBHOOK_URL, signing_keySIGNING_KEY, title【活动海报】周末技术沙龙, content_md本周末将举办**AI前沿技术分享沙龙**欢迎报名参加\n**时间**周六下午2点\n**地点**第一会议室, image_url_or_keyhttps://your-image-cdn.com/poster.jpg, # 公网可访问的图片URL use_image_keyFalse # 使用Markdown图片语法 ) # 示例3发送使用官方image_key的消息需要先上传图片 # 首先你需要有app_id和app_secret此步骤较复杂此处省略 # APP_ID your_app_id # APP_SECRET your_app_secret # image_key upload_image_to_feishu(local_chart.png, APP_ID, APP_SECRET) # 然后调用 # send_feishu_card_with_webhook(WEBHOOK_URL, SIGNING_KEY, 【图表报告】, 昨日流量走势图如下, image_key, use_image_keyTrue) if __name__ __main__: main()5. 部署与自动化让机器人持续运行脚本在本地测试成功后我们需要将其部署到服务器上并实现自动化触发。5.1 部署环境选择Linux服务器推荐稳定性高适合7x24运行。可以将脚本放在/opt/feishu_bot目录下。Docker容器实现环境隔离部署和迁移更方便。编写一个简单的Dockerfile即可。云函数/Serverless如果推送频率不高如每天几次使用腾讯云SCF、阿里云FC等云函数服务成本极低无需管理服务器。5.2 自动化触发方案Linux Crontab经典定时任务 编辑当前用户的crontabcrontab -e添加一行例如每天上午9点执行0 9 * * * /usr/bin/python3 /opt/feishu_bot/send_daily_report.py /opt/feishu_bot/cron.log 21系统服务Systemd 如果需要运行一个常驻的、监听消息队列的机器人可以将其注册为系统服务。 创建服务文件/etc/systemd/system/feishu-bot.service[Unit] DescriptionFeishu Notification Bot Afternetwork.target [Service] Typesimple Useryour_username WorkingDirectory/opt/feishu_bot ExecStart/usr/bin/python3 /opt/feishu_bot/bot_daemon.py Restarton-failure [Install] WantedBymulti-user.target然后使用sudo systemctl start feishu-bot启动服务。与业务系统集成 在你的业务代码如Django、Flask应用中在关键节点如订单完成、错误发生、任务结束时调用上面封装好的消息发送函数实现实时推送。6. 常见问题排查与进阶技巧在实际使用中你可能会遇到以下问题。这里提供一个快速排查清单。问题现象可能原因解决方案返回19001错误码签名验证失败。1. 检查SIGNING_KEY是否正确前后有无空格。2. 检查生成签名时timestamp是否为字符串格式的秒级时间戳且与请求头中的X-Lark-Request-Timestamp完全一致。3. 检查拼接字符串时是否使用了\n换行符。返回19999错误码一般性系统错误或请求格式问题。1. 检查Webhook URL是否完整无误。2. 检查请求头Content-Type是否为application/json。3. 检查消息体JSON格式是否合法可以使用在线JSON校验工具。消息发送成功但群内不显示1. 机器人被移出群聊。2. 安全设置中IP白名单限制。1. 检查机器人是否仍在目标群中。2. 如果设置了IP白名单请确保发送请求的服务器的公网IP在允许列表中。图片无法显示1. (使用img_key时)image_key无效或已过期。2. (使用Markdown链接时) 图片URL公网不可访问或飞书无法抓取。1.image_key有效期通常为30天需重新上传。2. 确保图片URL是https开头且无需登录即可访问。飞书对部分外网图片有防盗链或访问限制建议使用稳定图床。消息内容格式错乱Markdown语法错误或飞书不支持。飞书Markdown是子集不支持复杂HTML和某些特殊语法。尽量使用基础的加粗**、列表-、链接[]()、行内代码等。进阶技巧消息卡片更新飞书卡片支持“更新”功能。在第一次发送消息后会返回一个message_id。你可以通过另一个API使用相同的message_id发送新内容来替换原消息而不是发送一条新的。这对于发送实时更新的进度条、计数器非常有用。按钮交互在卡片的elements中可以添加button元素用户点击后飞书可以将交互事件推送到你预设的回调地址实现简单的交互逻辑如“确认收到”、“一键审批”等。限流与重试飞书机器人有调用频率限制具体查看官方文档。在代码中应加入简单的错误重试机制如对5xx错误重试2次和速率控制避免被限流。配置管理切勿将Webhook URL和Signing Key硬编码在脚本中。应使用环境变量或配置文件管理。例如import os WEBHOOK_URL os.environ.get(FEISHU_WEBHOOK_URL) SIGNING_KEY os.environ.get(FEISHU_SIGNING_KEY)在运行前通过export命令或在.env文件中设置。通过以上从原理到实践从代码到部署的完整拆解你应该已经掌握了使用Python驱动飞书机器人发送图文信息的全链路技能。这个小小的自动化工具能成为你团队效率提升的得力助手。

相关新闻