标签:#WorkBuddy #自动化 #GitHubActions #Python #量化 分类:人工智能 / 办公工具
我是一个股票交易者,每天开盘前都想快速扫一眼全球市场:美股三大指数收得怎么样、韩股有没有异动、国内政策面有什么新消息、原油黄金汇率怎么走。
最开始我让 WorkBuddy 每天定时帮我汇总推送。但很快踩了三个坑:
痛定思痛,我设计了一套完全不依赖个人电脑、零成本、推送到微信的方案。核心思路是:把"数据抓取+生成报告"这件事交给 GitHub Actions 云端定时跑,把"送达"交给 推送加(PushPlus) 直接推到微信。WorkBuddy 只负责帮我写代码和调试,写完就不再消耗积分。
最终实现效果:每天北京时间早 8 点,一条排版精美的股市早报自动出现在我的微信里,红涨绿跌一目了然。
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ GitHub Actions │ ──▶ │ Python 脚本 │ ──▶ │ 推送加 PushPlus │ ──▶ 📱 微信
│ (云端每天8点) │ │ 抓取+生成HTML早报 │ │ (推送到微信) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
免费 免费 免费(200条/天额度)三个关键点:
总成本:0 元/月。
需要注册 3 个免费账号:
账号 | 用途 | 费用 |
|---|---|---|
GitHub | 托管代码 + 定时运行 | 免费 |
推送加 pushplus.plus | 推送消息到微信 | 免费(需实名) |
微信 | 接收早报 | 免费 |
💡 推送加必须实名认证才能发消息(国内合规要求),在 verify.pushplus.plus 验证手机号即可,很快。
注册推送加后,在「个人中心」复制你的 token(一长串字符),后面要用。
新建 daily_stock_report.py,核心逻辑是:用新浪财经接口批量抓取行情 → 组装成 HTML → 调用 PushPlus 推送。
#!/usr/bin/env python3
"""每日股市早报 - 自动抓取市场数据并推送到微信"""
import requests
import os
import re
import time
from datetime import datetime, timezone, timedelta
PUSHPLUS_TOKEN = os.environ.get('PUSHPLUS_TOKEN', '')
PUSHPLUS_URL = 'https://www.pushplus.plus/send'
SINA_URL = 'https://hq.sinajs.cn/list={}'
SINA_HEADERS = {
'User-Agent': 'Mozilla/5.0',
'Referer': 'https://finance.sina.com.cn',
}
# 新浪财经:美股 / 韩股 / A股
SINA_STOCKS = {
'US': [('gb_dji','道琼斯工业指数'), ('gb_inx','标普500指数'), ('gb_ixic','纳斯达克综合指数')],
'KR': [('b_KOSPI','KOSPI指数')],
'CN': [('sh000001','上证指数'), ('sz399001','深证成指'), ('sz399006','创业板指')],
}
# 大宗商品 & 汇率
SINA_COMMODITIES = [
('hf_CL','WTI原油'), ('hf_OIL','布伦特原油'),
('hf_GC','COMEX黄金'), ('hf_SI','COMEX白银'),
('fx_susdcny','美元/人民币'),
]数据解析(新浪返回的是 var hq_str_gb_dji="名称,现价,涨跌幅,..." 格式,需要按前缀用不同解析器):
def extract_sina_data(text):
m = re.search(r'"(.+?)"', text)
return m.group(1).split(',') if m and m.group(1) else None
def parse_sina_gb(parts): # 美股 gb_ 前缀
if not parts or len(parts) < 5: return None
try:
return {'price': float(parts[1]), 'change_pct': float(parts[2]), 'change': float(parts[4])}
except: return None
def parse_sina_b(parts): # 指数 b_ 前缀
if not parts or len(parts) < 4: return None
try:
return {'price': float(parts[1]), 'change': float(parts[2]), 'change_pct': float(parts[3])}
except: return None
def parse_sina_cn(parts): # A股 sh/sz 前缀
if not(parts) or len(parts) < 4: return None
try:
prev, price = float(parts[2]), float(parts[3])
return {'price': price, 'change': price-prev, 'change_pct': (price-prev)/prev*100}
except: return None批量抓取(一次请求拿全部,减少网络开销):
def fetch_sina_batch(symbols, parser_map):
if not symbols: return {}
url = SINA_URL.format(','.join(symbols))
try:
r = requests.get(url, timeout=15, headers=SINA_HEADERS)
r.encoding = 'gbk'
results = {}
for line in r.text.strip().split('\n'):
m = re.match(r'var hq_str_(\S+?)="', line.strip())
if not m: continue
sym = m.group(1); parser = parser_map.get(sym)
if not parser: continue
parts = extract_sina_data(line)
if parts:
d = parser(parts)
if d: results[sym] = d
return results
except Exception as e:
print(f'[新浪] 失败: {e}'); return {}财经要闻(新浪滚动新闻接口):
def fetch_sina_news():
url = 'https://feed.mix.sina.com.cn/api/roll/get?pageid=153&lid=2516&num=15&page=1'
try:
data = requests.get(url, timeout=10, headers={'User-Agent':'Mozilla/5.0'}).json()
return [i.get('title','').strip() for i in data.get('result',{}).get('data',[]) if i.get('title')][:12]
except: return []格式化 + 推送(中国惯例红涨绿跌):
def fmt_change(d):
pct = d['change_pct']
color = '#e0322d' if pct >= 0 else '#2da44e' # 红涨绿跌
arrow = '涨' if pct >= 0 else '跌'
return f'<span style="color:{color};font-weight:bold;">{d["price"]:,.2f} {arrow}{abs(pct):.2f}%</span>'
def push_to_wechat(html, date_str, weekday):
if not PUSHPLUS_TOKEN:
print('⚠️ 未设置 PUSHPLUS_TOKEN'); return False
payload = {'token': PUSHPLUS_TOKEN, 'title': f'📊 每日股市早报 - {date_str} {weekday}',
'content': html, 'template': 'html'}
r = requests.post(PUSHPLUS_URL, json=payload, timeout=30)
res = r.json()
print('✅ 推送成功' if res.get('code')==200 else f'❌ 失败: {res}')
return res.get('code') == 200完整脚本(含 HTML 报告生成、情绪总结等)已放在文末仓库链接,可直接 clone 使用。
在仓库新建 .github/workflows/daily-report.yml:
name: 每日股市早报
on:
schedule:
- cron: '0 0 * * *' # 每天 00:00 UTC = 北京时间 08:00
workflow_dispatch: # 支持手动触发测试
jobs:
push-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install -r requirements.txt
- name: 运行早报脚本
env:
PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }}
run: python daily_stock_report.py⚠️ 重要:
PUSHPLUS_TOKEN建议用 GitHub 仓库的 Secrets 保存(Settings → Secrets → Actions → New secret,Name 填PUSHPLUS_TOKEN,Value 填你的 token),不要明文写进代码,避免泄露。本文为简化演示用了硬编码,正式使用请务必用 Secrets。
requirements.txt 只需一行:
requestsdaily_stock_report.py、requirements.txt、.github/workflows/daily-report.yml 推上去。这些坑都是我实打实踩过的,帮你省时间:
Referer: https://finance.sina.com.cn 会拿不到数据,且返回是 GBK 编码,记得 r.encoding='gbk'。项目 | 费用 | 说明 |
|---|---|---|
GitHub Actions | 免费 | 每月 2000 分钟额度,本任务每天约 1 分钟 |
推送加 PushPlus | 免费 | 每天 1 条,额度 200 条/天 |
新浪财经 API | 免费 | 无需 Key |
WorkBuddy | 0 积分 | 仅写代码时用,写完即停 |
对比 WorkBuddy 自带自动化:每天约 50 积分,一个月 1500 积分;本方案把这部分完全省下,早报还不受电脑开关机影响。省下的积分留着做深度调研等真正需要 AI 的任务。
这套方案的核心价值是把"定时+推送"这种确定性任务从本地搬到云端,你只需要在 WorkBuddy 里把脚本写好、调通,剩下的交给 GitHub 免费服务器。
如果你想扩展,还可以:
希望这篇教程帮你也搭起自己的免费早报系统。有问题欢迎评论区交流。
完整代码仓库:本文脚本可访问 GitHub 搜索 daily-stock-report(或直接按文中代码自行拼装,约 200 行)。
原创内容,转载请注明出处。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。