はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

概要

今まで、はてなダイアリー(d.hatena.ne.jp/meganii)の記事は移行せずにそのまま残していました。 しかし、Scrapboxのユーザー会に参加して過去コンテンツの重要性に気付き、今のブログに全て集約したいと考えました。

そこで、はてなブログを経由させて、独自ドメインのブログに記事を全て移行しました。

その結果、はてなダイアリーからはてなブログにブックマークを含めて簡単に移行できました。 その後の独自ドメインへの移行も、ページ価値を引き継いで、問題なく移行できました。

移行理由

Scrapboxのユーザー会に参加して、過去に書かれた文章と今の自分を繋ぐことができるという点に感銘を受けました。

ブログをScrapboxに移行することも考えました。 しかし、ブログはあくまでもブログとして記事を残し続け、少しでも過去記事への参照が容易となることを目指します。

よって、はてなダイアリーのコンテンツを独自ドメインのブログに移行しました。

結果どうだったか

移行した直後の記事のデザイン崩れや、メタデータ(タグやカテゴリ)の損失は仕方ないと割り切って移行しました。 えいやっと移行したので、重複コンテンツやうまくGoogleに認識されない不安に襲われましたが、なんとかなったようです。

過去のコンテンツも自ブログに全て移行したことによって、昔書いた記事を読み返すきっかけとなり、こんなこと考えていたなと振り返ることができました。

また、過去記事へアクセスも、Googleに移行が認められたような挙動になっていましたので安心しました。

移行の考え方

ブログ移行をGoogleに伝えるには301リダイレクトが推奨されています。

検索エンジンの結果で表示されるページのURLを変更する必要がある場合は、サーバーサイドの301リダイレクトを使用することをおすすめします。これは、ユーザーや検索エンジンが正しいページにたどり着くことを保証する最善の方法です。ステータスコード301は、ページが別の場所に完全に移転したことを意味します。
ページの URL の変更と 301 リダイレクトの使用 - Search Console ヘルプ

しかし、はてなダイアリー、はてなブログの無料版ではこの301リダイレクトを設定できません。

例えば、1か月だけはてなブログProに加入することでリダイレクトをできるらしいのですが、301リダイレクト処理は恒常的に行うべきものらしいので選択肢として外しました。

調べてみると、簡単なJavaScriptによるリダイレクトであればGoogleのクローラーが解釈でき、移行元から移行先にページの価値が引き継がれるようです。

はてなダイアリーでは、JavaScriptの設定方法が分からなかったので、一旦はてなブログに切り替えてからであれば設定できます。

よって今回は、このJavaScriptによるリダイレクトによって、記事を移行させます。

やったこと

  1. Google Search Consoleに3つのブログを追加しておく
  2. はてなダイアリーからはてなブログへの移行処理
  3. はてなブログから記事エクスポート
  4. MT形式をMarkdownに変換
  5. はてなブログにJavaScriptによるリダイレクトを設定する
  6. GoogleにIndexされるのを待つ

1. Google Search Consoleに3つのブログを追加しておく

どこまで効果があるかわかりませんが、Googleにそれぞれ自分の所有サイトであることを伝えるために、Google Search Console上で以下の3つのサイトを追加しました。

  1. 移行元(はてなダイアリー)
  2. 経由先(はてなブログ)
  3. 移行先(独自ドメインのブログ)

2. はてなダイアリーからはてなブログへの移行処理

ブログ移行って面倒だなぁと思っていましたが、いざやってみるとなんてことはなく、以下の記事に従うと簡単に移行できました。

はてなダイアリーからのインポート(ブログの移行) - はてなブログ ヘルプ

STEP1記事のインポート、STEP2はてなブックマークの移行、STEP3記事のリダイレクトのボタンをぽちぽち押していけば、うまく設定できました。

はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

以下、完了時の画面です。この状態ではてなダイアリーへアクセスすれば、自動的にはてなブログへリダイレクトされるようになります。

はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

はてなブックマークも以下の通り、d.hatena.ne.jp/meganiiからmeganii.hatenablog.comに変更されてます。

はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

3. はてなブログから記事エクスポート

問題なくはてなダイアリーからはてなブログにサイトが移行されたことを確認した後に、はてなブログから記事をエクスポートします。

記事データをエクスポートできるようにしました。ブログのバックアップ等にご利用ください - はてなブログ開発ブログ

4. MT形式をMarkdownに変換

記事は、MT(Movable Type)形式でエクスポートされます。そのため、MT形式をMarkdownに変換します。

カテゴリとタグの扱いが甘いですが、まあよしとして移行しました。

mt2md.rb

# frozen_string_literal: true

require 'yaml'
require 'time'

def parse(filepath)
  File.open(filepath) do |f|
    contents = f.read
    posts = contents.split('--------')
    posts
  end
end

def extract(post)
  yaml, body = ''
  content = post.split('-----')
  begin
    yaml = YAML.safe_load(content[0])
    body = content[1].gsub!(/^BODY:/, '')
  rescue => exception
    puts content[0]
    puts exception.message
  end
  { frontmatter: yaml, body: body }
end

posts = parse('meganii.hatenablog.com.export.txt').map { |post| extract(post) }
posts.each do |post|
  date = Time.strptime(post[:frontmatter]['DATE'], '%m/%d/%Y %H:%M:%S')
  slug = post[:frontmatter]['BASENAME'].split('/').last
  filename = "../content/blog/#{date.strftime('%Y-%m-%d')}-#{slug}.md"
  category = post[:frontmatter]['CATEGORY']

  open(filename, 'w') do |md|
    md.puts '---'
    md.puts "title: #{post[:frontmatter]['TITLE']}"
    md.puts "date: #{date}"
    md.puts "lastmod: #{date}"
    md.puts "slug: #{slug}"
    md.puts "category: ['Tech']"
    md.puts "tags: ['#{category}']"
    md.puts 'published: true'
    md.puts '---'
    md.puts
    md.puts post[:body]
  end
end

replace_url.rb

URLを現在のURLに変換します。

# frozen_string_literal: true

require 'uri'

Dir.glob('content/*/*.*') do |file|
  buffer = File.open(file, 'r') { |f| f.read() }
  list = URI.extract(buffer, ['http']).select { |a| a.start_with? 'http://d.hatena.ne.jp/meganii' }.map { |x| x.gsub(')','') }
  list.each do |a|
    uri = URI.parse(a)
    len = uri.path.split('/')

    unless len.length > 3
      p uri
      buffer.gsub!(a, 'https://www.meganii.com/')
      next
    end

    year = len[2].slice(0, 4)
    month = len[2].slice(4, 2)
    date = len[2].slice(6, 8)
    slug = len[3]
    buffer.gsub!(a, "https://www.meganii.com/blog/#{year}/#{month}/#{date}/#{slug}")
  end

  File.open(file, 'w') { |f| f.write(buffer) }
end

5. はてなブログにJavaScriptによるリダイレクトを設定する

リダイレクトのJavaScriptを記事下と、フッタに記述しました。

記事下

<p>移転しました。
<script type="text/javascript" language="javascript">
<!--
    var domain = "https://www.meganii.com/blog/";
    var path = location.pathname.substr(6).replace(/\//g, "");
    var slug = path.substr(8);
    var date = path.substr(0, 8);
    var yyyy = date.substr(0, 4);
    var mm = date.substr(4, 2);
    var dd = date.substr(6, 2);
    var url = domain + yyyy + "/" + mm + "/" + dd + "/" + slug + "/";
    if (location.pathname === '/') {
        url = 'https://www.meganii.com/'
    }

    document.write("<a href=\"" + url + "\">" + url + "</a></p>");

   // リダイレクト
  setTimeout("redirect()", 3000); // 3 sec
  function redirect(){
    location.href = url; 
  }
 
   // canonical の書き換え
  var link = document.querySelector("link[rel=canonical]");
  link.href = url;
-->
</script>

フッタ

<script type="text/javascript" language="javascript">
  <!--
  // リダイレクト
  if (location.pathname === '/') {
    setTimeout("redirect2home()", 3000); // 3 sec
  }

  function redirect2home(){
    location.href = 'https://www.meganii.com/'; 
  }
 
 // canonical の書き換え
 var link = document.getElementsByTagName("link")[0];
 link.href = 'https://www.meganii.com/';
  -->
</script>

はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

6. GoogleにIndexされるのを待つ

  • 移行直後: 検索結果にd.hatena.ne.jp/meganiiのみ表示される。
  • 移行してしばらく: 検索結果にd.hatena.ne.jp/meganiimeganii.hatenablog.comが表示される。
  • 2、3日後: 検索結果にmeganii.hatenablog.comのみ表示される。
  • 1週間後: 検索結果にwww.meganii.comが表示される。

Backlinks

静的サイトジェネレータHugo
Hugo入門 静的サイトジェネレータ「Hugo」でシンプルブログサイトを構築する 静的サイトジェネレータ「Hugo」インストール 静的サイトジェネレータ「Hugo」〜公開方法〜 サイト構築 Hugoのテーマでsubmoduleを使う方法 HugoでのシンタックスハイライトにPython Pygmentsが不要となった HugoのRelated Contentを利用して関連記事を表示する gulpで画像の最適化 Hugoソースコードリーディング〜Taxonomy〜 Render Hooks for Code Blocksを利用してコードブロックにファイル名を表示する Hugoでブログカードを作成する(resources.GetRemote利用) Templates 【Hugo】Partial Templateでは複数returnを記述する早期Returnを使えない 【Hugo】images.TextでOGP画像を生成する Shortcodes Hugo Shortcodesの作り方 HugoのShortcodesを利用してAmazon紹介リンクタグを作成 HugoでAMP対応のブログカードを作る AMP対応 AMP向けのミニマルCSSフレームワーク「1BX」をHugoに導入した AMPページの最適化〜ぼくのAMPサイトがこんなに遅い訳がない〜 AMP OptimizerによるAMPのさらなる最適化 AMP Service WorkerでPrefetch Linksを実現する Data Driven Content Hugoで人気記事を表示するためJSONを返すAPIサーバを作りData-driven Contentを試してみた Tailwind CSS HugoでTailwindCSSを利用しAMP Validなページを生成する ビルド npm-run-allでローカルAPI serverとHugo serverを同時に実行する GitHub Actionsのスケジューラ実行を利用して定期的にビルドする Circle CIでHugoのビルド・デプロイを実行する コンテンツ作成 Git pre-commitフックでFrontmatterの「更新日時」を自動更新する Hugoでブログ記事一覧ページ(ブログアーカイブページ)を作成する 移行 はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました JekyllからHugoへの移行ポイント Hugoで生成した静的サイトのホスト先をさくらVPSからNetlifyに変更する 書籍
2017-12-31