Hatena Blog から Jekyll へのコンバーター
昔のブログは Hatena Blog でホスティングしていたのですが、 一念発起してこちらの Jekyll ベースのブログにコンバートしてインポートしました。
Hatena Blog のエクスポート時のフォーマットは MovableType 形式 なので、 それを一括で変換してインポートする感じに適当スクリプトを作りました。
予め reverse_markdown
gem をインストールしておく必要があります。
コード
# frozen_string_literal: true
require 'erb'
require 'reverse_markdown'
require 'time'
require 'uri'
contents_all = File.readlines('xxx.hatenablog.com.export.txt')
puts contents_all.length
chunked = contents_all.chunk_while do |i, _|
!(i =~ /^--------\Z/)
end
puts chunked.to_a.size
class Article
# @return [Array]
attr_accessor :raw
# @return [Hash]
attr_accessor :meta
# @return [Array]
attr_accessor :body
# @return [Array]
attr_accessor :comment
# @return [String]
attr_accessor :body_markdown
def initialize(arr)
@raw = arr
@meta = {}
@body = []
@comment = []
@raw.pop # rm term
parse!
convert_body!
end
def parse!
state = :meta
original = @raw.dup
while true
line = original.shift
break unless line
case state
when :meta
if line =~ /-----/
state = :body
next
end
line =~ /([A-Z ]+): (.+)?/
@meta[$1] ||= []
@meta[$1] << $2
when :body
if line =~ /-----/
state = :comment
next
end
@body << line
when :comment
@comment << line
end
end
end
def convert_body!
b = @body.dup
b.shift # rm BODY: line
@body_markdown = ReverseMarkdown.convert(b.join, github_flavored: true)
end
end
articles = chunked.map do |chunk|
Article.new(chunk)
end
class Publisher
attr_accessor :article
attr_accessor :title
attr_accessor :publish_datetime
attr_accessor :categories
attr_accessor :body
attr_accessor :content
attr_accessor :filename
# @param [Article] article
def initialize(article)
@article = article
@title = article.meta['TITLE']
@publish_datetime = article.meta['DATE']
@categories = article.meta['CATEGORY']
@body = article.body_markdown
normalize!
end
def publish
template = <<EOS
---
layout: post
title: "<%= @title %>"
date: <%= @publish_datetime.to_s %>
categories: [<%= @categories.join(', ') %>]
---
<%= @body %>
EOS
b = binding
@content = ERB.new(template).result(b)
@filename = generate_filename
end
def normalize!
@title = @title[0] || '無題'
@publish_datetime = Time.strptime(@publish_datetime[0], '%m/%d/%Y %H:%M:%S')
@categories = @categories || ['post']
end
def generate_filename
ymd = @publish_datetime.strftime("%Y-%m-%d")
title = @title.lstrip[0, 16].gsub(/[\/.:]/, '_')
"#{ymd}-#{URI.escape(title)}.markdown"
end
end
publishes = articles.map do |article|
p = Publisher.new(article)
p.publish
p
end
publishes.each do |pub|
puts pub.filename
File.open('_posts/' + pub.filename, 'w') do |f|
f.write(pub.content)
end
end
とりあえずざっくりでインポートはできるのですが、 元データもそんなに安定してなかったりなので結構手作業で直しちゃう感じである程度整えたところで手仕舞いとしました。
冗長な感じだったり puts
あるねぇな感じだったりするのは手探りでやってたままのコードだからです、ご容赦ください!
よかったらお使いくださいませ〜。
ライセンス
おわり