当 Agent 自己会发博客:OpenHanako 接入 Blogger 自动发文实录
让 AI 写完文章自动发布到 Blogger,记录配置 OAuth 和自动发文的完整过程与技术细节。
我的写作助手每周给我写技术文章,写完之后还得我自己手动复制粘贴到博客上。一次两次还行,每周都来——我肯定坚持不下去。
于是我做了一个决定:让它在写完文章之后,自己发出去。
这篇文章就是整个接入过程的记录。不是什么官方教程,是我踩坑的真实经历。
核心链路:只有两步
自动发文这件事,拆到最底层就两步:
- 获取授权:让 OpenHanako 有权限以我的身份发文章
- 调用 API:把 Markdown 转成 HTML,POST 到 Blogger
听起来简单,但每一步都有坑。
先看授权。Blogger 用的是 Google 的 API,走 OAuth 2.0。这意味着你不能只拿一个 API Key 就完事——你需要一个代表 "你" 的 token。
OAuth 2.0 的流程是:
- 你去 Google Cloud Console 注册一个应用,声明 "这个应用要访问 Blogger"
- 你授权这个应用访问你的博客
- 应用拿到一个 refresh token,存起来
- 以后每次发文章,用 refresh token 换一个临时的 access token
- 拿 access token 调 API
前面两步是手动的,后面三步是自动的。所以配置是一次性的,之后脚本自己跑。
踩坑一:OAuth 同意屏幕
第一次配 Google Cloud Console 的时候,我卡在最基础的步骤上。
新建项目、启用 Blogger API,这些都还好。到了配 OAuth 同意屏幕的时候,我选了 "外部" 用户类型——因为这是个人项目,不需要公司内部认证。
然后我遇到了第一个错误:"应用尚未完成 Google 验证流程"。
Google 的政策是:如果你的应用没有通过验证,只有你手动添加的测试用户才能授权。我忘了把自己加进测试用户列表。
解决办法很简单:去 OAuth 同意屏幕页面,找到「测试用户」部分,把自己的 Gmail 加进去。等一两分钟生效,重新授权就好。
踩坑二:网络环境
配好了 OAuth,拿到了 client_secret.json,以为万事大吉了。结果脚本一跑——连接超时。
我的开发环境在中国,Python 的 requests 库直连 Google API 的时候 SSL 握手失败。查了半天,发现是 urllib3 的底层 SSL 实现跟网络环境的兼容性问题。
解法也不复杂:换成 Python 标准库的 urllib.request,配合自定义 SSL 上下文跳过证书验证(反正 Google 的证书没问题,纯粹是握手协议的问题):
import ssl
import urllib.request
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
req = urllib.request.Request(url, data=body)
with urllib.request.urlopen(req, context=ctx, timeout=10) as resp:
result = json.loads(resp.read().decode())
如果你也在类似的环境下,遇到 requests 连 Google 超时的问题,试试这个方案。
最终的发文脚本
把整条链路串起来,核心逻辑就这几步:
# 1. 读配置
config = json.loads(open('blogger_config.json').read())
# 2. 用 refresh_token 换 access_token
body = urllib.parse.urlencode({
'refresh_token': config['refresh_token'],
'client_id': config['client_id'],
'client_secret': config['client_secret'],
'grant_type': 'refresh_token',
}).encode()
req = urllib.request.Request(TOKEN_URI, data=body)
resp = urllib.request.urlopen(req, context=ctx)
access_token = json.loads(resp.read())['access_token']
# 3. Markdown 转 HTML
html = markdown.markdown(md_text, extensions=['fenced_code', 'tables'])
# 4. POST 到 Blogger API
req = urllib.request.Request(POSTS_URL, data=json.dumps({
'title': title, 'content': html, 'labels': labels
}).encode())
req.add_header('Authorization', f'Bearer {access_token}')
resp = urllib.request.urlopen(req, context=ctx)
post_url = json.loads(resp.read())['url']
两条线的写作流程
还有一件事是发完第一篇文章之后才想明白的:本地版本和博客版本应该分开。
本地文件可以随便写——项目名、具体场景、内部上下文,想写就写。但发到博客上的内容,必须把敏感信息替换掉。比如我的项目名 "MyProject" 在本地出现没问题,到博客上就得改成 "这类系统"。
所以现在的写作流程变成了:
- 调研 → 写完整版 → 存本地
- 复制一份,把项目名、个人身份信息替换成通用说法
- 发布到 Blogger
- 本地文件末尾追加已发布的链接
本地是知识库,博客是窗口。两套内容,同一个源头。
最后说一句
接入 Blogger API 本身不复杂——官方文档写得清楚,POST 请求发出去就完事。真正的坑都在边缘:OAuth 的配置细节、网络环境的兼容性、内容脱敏的策略。
但一旦跑通了,收益是实打实的:文章写完自动发布,不用复制粘贴,不用打开浏览器后台。对于一个每周要产出技术内容的 Agent 系统来说,这是最后一块拼图。
现在我的写作助手写完文章会自己收拾干净、自己出门、自己去博客上贴好。我只需要在它发之前瞄一眼内容有没有问题。
这大概就是 AI-Native 工作流的样子——不是 AI 帮你做一部分,剩下的人来收尾。而是 AI 做完一整条链路,人只在最关键的地方点一下头。
评论
发表评论