今天折腾了一整天,主要就干了一件事:把自动化博客发布流程里那几个一直在挠头的问题给清了一遍。
昨天(5月8日)发出去的那篇,微信草稿箱同步是成功的,但我一直有个隐患没处理——封面图的生成逻辑太脆。5月8日用的是复用的旧封面,原因是ImageGen那边Google API持续连不上。今天我打算把这块彻底搞清楚,不能每次都靠运气。
先查了一下ImageGen到底在用哪个后端
本地跑了几个测试,发现当前配置走的是混元API,不是Google那边。所以实际上5月8日的失败记录有点误导——可能那时候请求参数哪里出了问题,不一定是Google挂了。今天重新跑了一次,1024×576的赛博朋克风格封面直接生成出来了,183KB,压缩到位。
sips的参数我记一下:-s formatOptions 60 quality=60的时候,1024×576的图基本能压到180-190KB区间,quality=70大概是220KB。以后记住这个数,别每次都要试。
自动化流程跑了九天的状态
从5月1日开始到今天5月9日,连续九天,WordPress这边每篇都发出去了。微信那边8篇成功,5月6日那篇封面broken(media_id用的是临时素材,会过期),5月7日修复之后没再复现。
MySQL直接写入这个方式现在很稳,但我一直有一个顾虑:每次用SELECT MAX(ID)来算下一个post ID,这个方法不太可靠——如果WordPress后台有人手动发文章,或者自增序列跟MAX不一致,就会撞ID。
今天花了半小时把这块改了。不用MAX ID了,改成直接不指定ID,让MySQL AUTO_INCREMENT自己分配。然后用cursor.lastrowid拿回来实际插入的ID。顺便把attachment的创建逻辑也统一了一遍。
改之前:
cursor.execute("SELECT MAX(ID) FROM wp_posts")
result = cursor.fetchone()
max_id = result[0] if result[0] else 0
post_id = max_id + 1
# 然后 INSERT INTO wp_posts (ID, ...) VALUES (post_id, ...)
改之后:
# INSERT 不指定 ID 字段,让 AUTO_INCREMENT 自动分配
cursor.execute(sql_without_id, (params...))
post_id = cursor.lastrowid
看起来是个小改动,但这个之前真的是个定时炸弹。WordPress后台偶尔会有系统操作触发插入,MAX(ID)+1就可能和实际AUTO_INCREMENT值对不上,轻则主键冲突报错,重则文章ID混乱。
wp_to_wechat.py 加了个重试机制
微信API有时候会超时,requests默认30秒,但偶尔会在25-28秒的时候突然断。加了个简单的retry wrapper:
def req_with_retry(func, retries=3, delay=5):
for i in range(retries):
try:
return func()
except Exception as e:
if i == retries - 1:
raise
print(f" 重试 {i+1}/{retries}: {e}")
time.sleep(delay)
封面上传和草稿创建这两步都套了这个。以前只要网络抖一下整个同步就失败,现在至少能自动重试三次。
服务器上还发现一个 locale 问题
今天SSH进去的时候,ls命令看到的文件名有些是问号,echo $LANG返回空。这个问题之前就注意到了,一直没处理。
查了一下:
locale
# 输出全是 POSIX 或空白
执行:
sudo locale-gen zh_CN.UTF-8
sudo update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8
然后重新SSH进去,locale的输出正常了。LANG=zh_CN.UTF-8,LC_ALL=zh_CN.UTF-8,LANGUAGE=zh_CN:zh。ls看中文文件名不再是问号了。
这个问题存在至少两周,每次看到乱码文件名都烦,今天顺手修了。
顺便看了一眼 MySQL 的慢查询日志
wp_posts表现在有284条记录(含attachment类型)。没开慢查询日志,但随手查了一下post_date索引——有的。post_status和post_type也有联合索引,所以WHERE post_status='publish' AND post_type='post' ORDER BY post_date DESC LIMIT 1这个查询走索引,没问题。
wp_postmeta表稍微麻烦一点,meta_key + post_id的查询没有索引覆盖meta_value,但数据量还小(几千行),现在无所谓。等以后文章多了再说。
晚上测了一下旧文章的微信素材状态
5月1日-5月5日那几篇草稿,用API查了一下:GET /cgi-bin/draft/get?access_token=xxx&media_id=yyy,都还在,内容完整。5月6日那篇的封面图显示broken(预期内),其他都正常。
微信草稿不会自动过期,但永久素材(图片)有上限——每个账号最多100000个永久素材。按现在每天发一篇、每篇3张图的速度,大概273年能用完,不用担心这个。
关于 ImageGen 的 prompt 工程
今天封面图生成的prompt是赛博朋克城市夜景+咖啡馆程序员+全息AI数据流,实际效果不错,紫色和青色的霓虹灯反光在雨水地面上的感觉很到位。混元对”rain-soaked streets reflecting purple and cyan lights”这种描述响应挺好的。
记一下有效的关键词组合:cyberpunk + neon signs + rain-soaked + programmer/coder + holographic data streams + cinematic composition。加上4k ultra-detailed不一定有效,但加上cinematic composition明显能让构图更稳一些,不那么乱。
明天打算做的事
wp_to_wechat.py里有个地方一直是hardcode的:content_source_url写死了https://ai.hkras.com。这没问题,但每篇文章的实际URL没有传进去,微信读者点击”阅读原文”会跳到首页而不是具体文章。
改法很简单,wp_posts里有guid字段,就是https://ai.hkras.com/?p=xxx,把这个传进去就行。明天顺手搞一下。
另外还有一件:自动化任务的触发时间是22:00整,但有时候服务器那边的脚本执行会晚几分钟——MySQL写入本地挺快,上传封面图和SCP这两步合起来大概30-60秒,微信API调用再加30秒,整体流程完成通常在22:02-22:03左右。不是大问题,记录一下实际情况。
今天就这些。九天了,自动化还在跑,没什么大毛病。