Node.js
tumblr
Evernote
TumblrAPI
EvernoteAPI

Tumblrの投稿をEvernoteに移植して、検索機能を補完する(Node.js)

はじめに

Tumblrは、Web上のすべての情報が集約される素晴らしいSNSです。
ダッシュボードから気に入った投稿をリブログし続けるだけで、自分のブログページをアイデアやインスピレーションの宝庫にすることができます。

しかし、Tumblrには自分のブログ内の投稿を検索する機能がありません。
また、困ったことに、Tumblrの投稿は検索エンジンにも引っ掛かりづらい特徴があります。*参考
そのため、「あの投稿の詳細なんだっけ?」と思っても、その投稿を検索できる手段が無いのです。

それならば、Tumblrの投稿をEvernoteに移植して検索できるようにしよう!

ということで、この記事では自分のTumblrの投稿をEvernoteに移植する方法を紹介します。

手順

Tumblrの投稿をEvernoteに移植する手順は、次の通りです。

  1. Tumblrから投稿データを取得
  2. 取得した投稿データを読み込んでEvernoteに投稿

以下、それぞれの手順で使えるソースコードの一例を示します。

1. Tumblrから投稿データを取得

この手順では、Tumblr APIを利用して、Tumblrから投稿データを取得します。

Tumblr APIを利用するには、OAuthの認証情報が必要です。
認証情報の取得には、以下の記事が参考になります。

認証情報が取得できたら、下記コードの所定の箇所にコピペして実行してください。

getTumblrPosts.js
var fs = require('fs');

// Authenticate via OAuth
var tumblr = require('tumblr.js');
var client = new tumblr.createClient({
    consumer_key: '**********',
    consumer_secret: '**********',
    token: '**********',
    token_secret: '**********'
});

// Set method option
var blogName = '**********';
var offsetRange = 20,
    postNum = *****
    loopCount = Math.round(postNum/offsetRange);

var i = 0;
var outputJSON = {
    "posts": []
};

// Call recursive function
loop();

// Recursive function for to get blog post data
function loop() {
    // Get blog post data per 20 posts
    var thisOffset = 20 * i,
        option = { offset: thisOffset };
    client.blogPosts(blogName, option, function (_, data) {
        outputJSON.posts = outputJSON.posts.concat(data.posts);
    });
    i++;

    console.log(i + '投稿目');

    // Save blog post data per 1000 posts
    if(i%1000 === 0) {
        fs.writeFileSync('./data/blogPosts'+i+'.json', JSON.stringify(outputJSON, null, '    '));
        outputJSON = { "posts": [] };  // Reset variable
    }

    if (i < loopCount) {
        setTimeout(loop, 5000);  // Run per 5 seconds
    } else {
        // Save fractional blog post data
        fs.writeFileSync('./data/blogPosts'+i+'.json', JSON.stringify(outputJSON, null, '    '));
        console.log('Complete!');
    }
}

このコードを実行すると、1000投稿ごとの投稿データをローカルに保存することができます。
(ちなみに1000投稿ごとに切り分けた理由は、JSONなどのテキストファイルが256MBを超えると、メモリの関係で扱いが少し面倒になるためです *参考

なお、上記コードのblogName(ブログ名)postNum(投稿総数)は、userInfoメソッドで取得することができます。

userInfoメソッドの利用コード例
client.userInfo(function (_, data) {
    fs.writeFileSync('./userInfo.json', JSON.stringify(data, null, '    '));
});

参考サイト

2. 取得した投稿データを読み込んでEvernoteに投稿

この手順では、取得したTumblrの投稿データを読み込んで、Evernote APIを用いてEvernoteに投稿します。

Evernote APIを利用する際も、Tumblr APIと同様に、認証情報を取得する必要があります。
OAuth認証での利用も可能ですが、Developer Token一つだけで利用することも可能です。

Developer Tokenの取得は、以下のページより行なってください。

ただし、現在取得可能な認証情報はSandbox環境のみのようです。
(申請すれば、Production環境の認証情報を取得できるとの情報もあります *参考

今回の例では、Sandbox環境のEvernoteにTumblrのテキスト投稿のみを投稿します。

post2Evernote.js
var Evernote = require('evernote'),
    sleep = require('system-sleep'),
    fs = require('fs');

var DEVELOPER_TOKEN = "**********";

var option = { token: DEVELOPER_TOKEN, sandbox: true },
    client = new Evernote.Client(option),
    noteStore = client.getNoteStore();

// Read Tumblr data files in data dir
var dataDirPath = './data/';
fs.readdir(dataDirPath, function(err, fileNameList){
    if (err) throw err;
    // handle each post data
    fileNameList.forEach(fileName => {
        var jsonData = fs.readFileSync(dataDirPath + fileName, 'utf-8');
        JSON.parse(jsonData).posts.forEach(post => {
            // Post to Evernote if text post ('quote' and 'text')
            if(post.type === "quote" && post.slug) {
                createNote(post.slug, handleENML(post.text));
            }
            else if(post.type === "text" && post.slug) {
                createNote(post.slug, handleENML(post.trail[0].content_raw));
            }
        });
    });
});

// Upload post to Evernote
function createNote(postTitle, postBody) {

    // Set ENML(Evernote Markup Language)
    var nBody = '<?xml version="1.0" encoding="UTF-8"?>';
    nBody += '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">';
    nBody += "<en-note>" + postBody + "</en-note>";

    // Create note object
    var ourNote = new Evernote.Types.Note();
    ourNote.title = postTitle;
    ourNote.content = nBody;
    ourNote.notebookGuid = "*****";  // evernote notebook guid

    // Create Note by createNote method
    noteStore.createNote(ourNote).then(function(note) {
        console.log("Posted: " + note.title);
    }).catch(function (err) {
        console.log(err);
    });

    sleep(5000);  // Wait 5 seconds
}

// Remove HTML incompatible with ENML
function handleENML(text) {
    return text.replace(/<a .+?>/g, "").replace(/<\/a>/g, "").replace(/<br>/g, "<br/>").replace(/<figure .*?>(.*?)<\/figure>/g, "");
}

なお、ソースコード内のNotebookGUIDは、投稿先にしたいNotebookをブラウザで開くことで確認することができます。(下図参照)

参考サイト

画像を投稿したい場合

別途記事を書きましたので、そちらをご覧ください。
▶︎ Evernote APIで画像URLから画像投稿する(Node.js)

デモ

今回紹介した方法により、Tumblrの投稿をEvernoteで検索できるようになりました!

おぉ... この検索の早さ...。
Tumblrに負けず劣らず、Evernoteも素晴らしいサービスですね...。

終わりに

この記事では、自分のTumblrの投稿をEvernoteに移植する方法と、そのためのソースコードを紹介しました。
この方法により、Tumblrの投稿をEvernoteで検索できるようになります。

これで、どれだけリブログしても、投稿が埋もれてしまう心配がなくなることでしょう。
皆さんのリブログがもっと捗るようになることを祈ります。