工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

Boostnoteで下書きしたMarkdown文書をはてなブログに簡単に投稿するスクリプトを作成

概要

Boostnoteで下書きしたMarkdown文書をはてなブログに簡単に投稿するためのスクリプトを作成した。

背景と目的

私は、最近Boostnoteというノートアプリがお気に入りでよく使っている。 このアプリはMarkdown記法で書けるので便利なのだが、唯一ブログへの投稿機能がごく限られている点が不満だ。 そこで、どうにかBoostnoteで書いたものをはてなBlogへ簡単に投稿するためにスクリプトを作る。

詳細

方針

Boostnote自体には、はてなブログとの連携機能はないので、

  • Boostnoteで書いたら右クリック→Copy Note Link というコマンドを実行し、CSONファイルのリンクをクリップボードにコピー
  • その状態でスクリプトを実行すると、CSONファイルを読み出して自動的に投稿する

という感じにしたい。

CSONを読み出す

CSONファイルの読出しは、Pythonライブラリがあるのでそれを使う

pip install cson

Boostnoteから読み出す処理をまとめたものが以下。 read_clipboardメソッドは、クリップボードにコピーされたCSONファイルのリンクをたどり、 CSONファイルを読み出す。

class BoostNote():

    def __init__(self, _location):
        """
      """
        self.location = _location

    def read_clipboard(self):
        """
      クリップボードの文字列から読み出す
      """

        text = pyperclip.paste()

        j = text.index("]")
        notename = text[1:j]
        print notename

        k = text.index("(:note:")
        filename = text[k+7:-1]
        print filename

        # ノートを開いて読む
        fo = open(self.location + "/notes/" + filename + ".cson", "r")
        data = cson.loads(fo.read())
        fo.close()

        return data

なお、クリップボードのデータを使うには、pyperclipというライブラリが使える。

pip install pyperclip

投稿する

はてなブログAtomPub - Hatena Developer Center

上記リンクを参考にしたが、XMLを普段使わないせいか、結構てこずったが、どうにかできた。 ポイントは、XML文書内ではタグ内で改行やタブなどを適宜エスケープしなければならないということ。

投稿関連の処理をまとめたクラスを作成。

class HatenaBlog():

    def __init__(self, _hatena_id, _blog_id, _api_key):
        """
      """
        self.hatena_id = _hatena_id
        self.blog_id = _blog_id
        self.api_key = _api_key

        self._basic_url = "https://blog.hatena.ne.jp/" + HATENA_ID + "/" + BLOG_ID + "/atom"

    def post_article(self, title, body):
        """
      投稿する
      """

        url = self._basic_url + "/entry"

        headers = {
            "Content-Type": "application/xml",
            "Authorization": "Basic " + (self.hatena_id + ":" + self.api_key).encode("base64")[:-1]
        }

        # XMLの作成
        # 1行目のタイトルは本文には要らないので削除
        body = "\n".join(body.split("\n")[1:])
        # contentタグ内の文字列は適宜エスケープが必要
        body = body.replace("&", "&") # アンパサンドはエスケープ
        body = body.replace("<", "&lt;").replace(">", "&gt;") # <>はエスケープ
        # XML文書自体の改行は取る必要がある
        XmlData = u'''
      <?xml version="1.0" encoding="utf-8"?>
      <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app">
      <title>'''.replace("\t", "").replace("\n", "") + title + u'''</title>
      <author><name>dekuo-03</name></author>
      <content type="text/x-markdown">'''.replace("\t", "").replace("\n", "") + body + u'''
      </content>
      <app:control>
          <app:draft>yes</app:draft>
      </app:control>
      </entry>
      '''.replace("\t", "").replace("\n", "")
        # post
        req = urllib2.Request(url, data=XmlData.encode("utf-8"), headers=headers)
        resp = urllib2.urlopen(req)
        a = resp.read()

        return a.decode("utf-8")

という感じで、2つのクラスを使ってスクリプトを組んだところ、ちゃんと投稿できた!!!

# 定数
HATENA_ID = "はてなID"
BLOG_ID = "ブログID"
API_KEY = "APIキー"
LOCATION = u"Boostnoteのノート保存フォルダパス"

# 準備
hatenaBlog = HatenaBlog(HATENA_ID, BLOG_ID, API_KEY)
boostnote = BoostNote(LOCATION)

# boostnoteから読み出す
data = boostnote.read_clipboard()
print json.dumps(data, indent=4, ensure_ascii=False)

# 投稿する
resp = hatenaBlog.post_article(data["title"], data["content"])

print resp

まとめ

Boostnoteで下書きしたMarkdown文書をはてなブログに簡単に投稿することができた。ただ、画像の挿入などができていないので、のちのち改善したい(が難しそう)