背景
刚开始学弄公众号,发现竟然不支持markdown格式,发布到其他平台,还得重新编辑。。贼麻烦。
搜了下,有不少工具可以实现一键发布多个平台,但是要钱。
还是看看有啥开源方案吧。。。然后发现别人通过写谷歌插件可以实现这个功能。开源的有一个叫Wechatsync的工具,体验了一下将微信文章同步到其它平台,同步是同步了,但是同步后排版好像有点变形。
于是跑去研究Wechatsync的代码看看能不能自己改改调整下格式,作为一个后端仔,看了下工程感觉工作量也不少啊,自己就只是发一两个平台的,还是自己撸一个吧。
搜了些关于谷歌插件实现博客搬运的文章,也动手写了个插件的demo,这不行啊,得研究对应的js,不然数据怼不上去啊。。。
最终效果
没办法,只能用最low的办法了,上python + selenium,我按正常操作搞!
目前已经实现了从本地读取markdown文档以及图片,自动保存到微信以及csdn的草稿箱,效果如下
开发过程中遇到的问题
在开发的过程中主要遇到的几个问题比较耗时间,其他都是一些重复繁琐的工作,不值一提
- 微信上传图片的按钮会动态刷新导致找不到元素
- 微信如何填充文章到富文本编辑器中
- csdn图片上传问题
1.微信上传图片
看了一下,微信公众号不支持自家以外的图片链接,那就只能上传图片到微信了!想想都觉得麻烦。。我上传了图片然后再编辑文档选图片,不可能的,太繁琐了!
用selenium模拟上传图片本来就比较繁琐。。。没想到微信大佬还给我增加工作量!
input按钮就藏在图中的这一堆id = rt_rt_xxxxxxxx 的div中,通过观察CSS可以知道最后一个input按钮就是真正的。除了有多个input按钮来混淆视线外,当你鼠标滑过已上传的图片的缩略图的时候,还会不断地产生新的,作为一个后端仔,哪见过这场面。于是我又废了不少时间,解决这个问题。
解决方法是通过 MutationObserver 监听DOM变化,当有新的节点产生的时候就输出日志到控制台,然后通过selenium解析日志截取最新的节点ID,最后通过ID获取input按钮即可。
# 注入 JavaScript 代码以设置 MutationObserver,微信会刷新按钮,需要监控dom树的变化然后获取最新的按钮
script = """
const targetNode = document.querySelector("#app > div.weui-desktop-block > div.weui-desktop-block__main > div.weui-desktop-block__main__header > h2 > div.weui-desktop-block__main__header__extend > div > div > div"); // 你要观察的目标节点
// 创建一个 MutationObserver 实例
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) { const addedNode = mutation.addedNodes[0]; if (addedNode && addedNode.id) { console.warn('upload_div_id ' + addedNode.id); } }});
// 配置观察选项
const config = {
childList: true, // 观察子节点的添加和删除
attributes: false, // 观察属性变化
subtree: false // 观察所有子孙节点
};
// 开始观察目标节点
if (targetNode) {
observer.observe(targetNode, config); console.info('开始观察:', targetNode);
}
"""
# 执行注入的 JavaScript 代码
driver.execute_script(script)
# 获取浏览器控制台的日志
logs = driver.get_log('browser')
# 过滤出以 'upload_id' 开头的日志
filtered_logs = [log for log in logs if 'upload_div_id' in log['message']]
# 获取最新的日志
if filtered_logs:
latest_log = filtered_logs[-1] # 最后一条就是最新的日志
log = latest_log['message']
div_id = re.search(r'rt_rt_\w+', log)[0]
print("Latest log:" + latest_log['message'])
print("get div_id :" + div_id)
else:
print("No logs found with 'upload_id'.")
后来写笔记的时候想起,其实只要用selenium模拟鼠标移动到上传按钮处点击即可,用来混淆的div都是重叠在同一个位置,随便获取一个就能将鼠标移动过去然后触发鼠标的点击事件就可以了。
2. 如何填充文章到富文本编辑器中
富文本编辑器,编写内容后,会经过编辑器的js代码处理然后动态添加DOM树,所以我们只要将markdown文本转换成html后通过selenium执行Javascript代码插入DOM树就可以了
import markdown
# 读取 Markdown 文件
input_file_path = '学习环境安装minikube.md' # 替换为你的 Markdown 文件路径
output_file_path = 'output.html' # 输出的 HTML 文件路径
# 打开并读取 Markdown 文件
with open(input_file_path, 'r', encoding='utf-8') as f:
markdown_content = f.read()
# 将 Markdown 转换为 HTML
html_content = markdown.markdown(markdown_content)
一开始直接用的markdown库去转html,发现markdown语法解析出来,不尽人意,例如code片段识别有问题
于是就自己写段代码解析下,毕竟自己就用那几个语法。先把markdown读进来后,每行用正则表达式来截取下内容就可以了。
截取完后,就是转html了,通过浏览器的debug工具,查看富文本生成的html元素是啥样的,直接copy过来做模板,然后填充内容就好了。以图片为例,富文本编辑器生成的html元素如下,保存下来做模板,我们把其中的URL替换掉即可,这里我用jinja2库实现。
这里吐槽一句,当时弄这个的时候,最麻烦的就是代码片段的处理,我好不容易实现了一版后,微信大佬又改了,害得我又调一阵子样式,最终只能调成以下的样子,多了一行空格,原因是
大佬加了校验功能后,会强制给我再套一层span。
因为多套了一层span,在草稿阶段预览的时候,会不正常,无所谓吧,最终发布的时候能用就行,凑合一下吧。
3.优快云图片上传问题
本来csdn有支持导入markdown的功能相对微信来说是省事一些,但是又没省那么多,因为它不能先上传图片,必须要一边编辑文章一边上传图片!
这就导致我要想办法模拟删除图片以及上传图片的操作了。。。经过我的不懈努力最终搞定了
方法就是,先定位到失效的图片,然后在失效的图片后面上传图片,然后再删除失效图片。
这里麻烦的是新增图片或者删除图片都有可能会导致selenium获取的元素失效需要重新定位,让代码看起来很低效没有办法一次性选中元素后遍历操作
总结
总算搞完了,自己定制的工具用起来确实挺不错的。搞这玩意的时候,感觉自己搞了一波自动化测试。。希望微信大佬早点改完,不要老变动。