用 org-mode 写微信公众号

有朋友发邮件问我,你是怎么调用微信后台接口的?——他也想用 org-mode 写微信公众号,以为我用 org-mode 写完之后,直接调用微信接口发布出去的。

我并没有调微信接口,用的是最土的办法,先用 org-mode 写,输出成 HTML 格式,然后贴到微信提供的网页编辑界面里。

这里面有几个技术问题要解决,感兴趣的朋友可以看看——

(对不知道什么是 org-mode 的朋友:org-mode 是一种非常简单,同时非常强大的工具。可以用它来记笔记、维护待办事项、制定项目计划以及写作——全程使用最简单的纯文本。 本公众号所有文章均用 org-mode 完成)

1 文字格式的问题

微信公众号的网页编辑界面做的还可以,你从网页上复制一段内容,贴到微信公众号素材编辑窗口里之后,是能保存基本的格式的,比如原来是斜体的,贴进去还是斜体。

但是,一开始的时候我碰到了些问题,就是我原有的章节标题文字,拷贝粘贴进去之后看上去与普通正文并无区别。什么意思呢,你看下面这张图,是我从维基百科(https://en.wikipedia.org/wiki/Rich_Text_Format)上截的,注意其中的“History”,作为一个章节标题,它是用更大的字体显示的。

rtf-from-wiki.png

但是当我把这段文字拷贝粘贴到微信公众号编辑窗口里之后,你可以看到“History”变成与普通正文相同的字体显示了。

rtf-in-wechat.png

这时候我的心情是有点崩溃的,这什么破编辑器,完全不能用嘛。不过后来在网上查了一些其他代替的解决方案,比如有用 markdown-here 浏览器插件写公众号的,直接用 markdown 格式写,然后点一下插件按钮,把 markdown 文本转换成 HTML 的格式。我没有试过这种方案,但看完之后恢复了点信心,如果别人能搞定章节标题格式的问题,我没理由搞不定的嘛。更何况贴进去的那些链接文字显示是蓝色的,“citation needed”这段小文字贴进去以后也还是斜体,说明这个编辑器的确是支持格式化文本的拷贝粘贴的,所以我接下来研究一下章节标题的显示格式丢失问题吧。

做了几个实验之后就弄明白了问题所在——微信公众号它没有内置的 css 样式!我拷贝进去的内容,章节用 HTML 的 <h1><h2> 等表示,在普通的浏览器上,是有默认内置的 css 的,会把这些章节文字用比较合理的方式显示出来(字体更大、更粗,行间距更大,等等)。

所以解决的思路就很清楚了,把每一个 HTML 的 tag 都加上相应的 css 格式。这样做完全违反了“Separation of presentation and content”的设计原理(https://en.wikipedia.org/wiki/Separation_of_presentation_and_content),但是,谁让微信公众号这么奇葩不自带默认 css 呢!

在网上搜了一下“css inline”,找到一个用 php 实现的项目https://github.com/jjriv/emogrifier。稍微研究一下就放弃了,改用 apt-get search css inline 搜了一下 Debian 的软件仓库,发现系统自带了一个 python-pynliner。稍微封装了一下,写了一个 css-inline 的脚本,放在 system-config 项目里,其中用到了一个默认的 css,来自于 Firefox 的 markdown-here 插件,位于 ~/system-config/etc/markdown-here.css

(写到这里,其实已经很明白了,微信公众号是非常违背互联网精神的。想插入一个链接都不行,你看我上面发的那些长长的链接,太丑了… 所以以后我的每篇公众号都会与 github 上的博客同步发布,望关注的诸君需要时“点击原文”以便点击文中链接。)

另外还有一个地方需要特殊处理,那就是微信公众号对 <pre> 标签处理有问题,不会保留里面的换行,必须把换行替换成 <br/> 才可以。这个我也在 css-inline 里处理了。

#!/bin/bash
echo hello

上面这段代码,不特殊处理的话,在微信里显示是这样的:

script-in-wechat.png

2 图片的问题

写完 org-mode 并输出成 HTML 之后,直接用浏览器本地打开,拷贝、粘贴到微信公众号的话,会有一个问题。那就是你所有的本地图片,是不会自动插入到浏览器里的。

解决的方法有两种:

  1. 自己手动上传、插入每张图片
  2. 把文章和图片先一起发布到 Github 的博客上,然后再打开相应网址,把图文一起拷贝、粘贴到微信公众号里。

    这种情况下,因为图片来源于网络,微信公众号会自动把图片抓取回来,保存到它的图库里。

    但是很无奈的是,有时候抓图会失败。目前不知道原因,但有可能跟重复抓图有关系。同一张图片,第二次拷贝、粘贴到微信公众号里,就会提示有 N 张图片粘贴失败。但又不是每次都所有的图片都失败。所以可能是个 Bug。

3 中英文空格、断行的问题

首先,在写 org-mode 的时候,我现在已经选择不断行了,否则生成 HTML 之后,如果原文在两个汉字中间有断行,展示出来的页面在这两个汉字之间就会有个空格。所以我写了个脚本,可以自动把以前写的有汉字间断行的文字重新拼接回去。这个脚本在 ~/system-config/bin/wrap-cjk

其次,就是汉字与英文混排时加不加空格的问题。我认为在现有的技术条件下,尤其是在 HTML 网页中显示,是应该加空格的。所以我写了个脚本,可以自动处理中英文之间的空格。这个脚本在 ~/system-config/bin/space-cjk-en

注意这些脚本都不是 100%可靠的,所以写完发布前需要自己认真校对几遍。比如前一篇公众号文章里“大V”就被脚本分割成了“大 V”,被我自己改回来了。

4 总结

所以,我用 org-mode 写一篇微信号,需要以下步骤:

  1. 写文章、校对 
  2. 用 wrap-cjk、space-cjk-en 脚本处理 
  3. 输出 HTML
  4. css-inline 脚本处理 
  5. 上传 Github,浏览器打开、样对 
  6. 拷贝、粘贴到微信公众号里 
  7. 最后一次校对 
  8. 发布

我去,写公众号太累了。