読者です 読者をやめる 読者になる 読者になる

0番染色体

科学は全世界を照らす光である

はてなブログのキーワード自動リンクを停止する

はてなブログは無料でも非常に便利に利用できる優良なブログサービスですが,「キーワード自動リンク」という機能だけはありがた迷惑です.本記事では,この機能を停止するために当ブログで行っていることを紹介していきます.

記事全体の流れとしては,まずキーワード自動リンクとは何かという説明から始め,それを解決するための方策3つのメリットとデメリットを紹介した後,当ブログが採用する手法について詳しく説明します.記事の最後では,この手法を自動化するためのRubyスクリプト(Markdown専用)も紹介しています.

キーワード自動リンクとは

はてなブログで普通に記事を書いていると,文章の随所に「キーワード自動リンク」なるものが貼られます.具体例を示しておきましょう.下に引用するのは,当ブログの過去記事の冒頭部分です.

Maximaは有名なオープンソースの数式処理システムです. 現在,最もよく使われている数式処理システムはおそらくMathematicaMapleですが, これらのソフトウェアは主に大学や研究機関で使用される高額な商用ソフトウェアで個人購入には向きません.

あちこちに「文字色が周りと異なり,下線が引かれている」箇所があるかと思います.これがキーワード自動リンクです.はてなブログの記事中に登場したはてなキーワードに登録されている単語に自動的にリンクを貼る機能なのですが,はっきり言って目障りです.また,上の引用中のMapleは数式処理ソフトMapleについて言及しているにも関わらず,自動的に貼られたキーワードリンクはPHPのWebアプリケーションフレームワークMapleに関するものです(2015/05/20現在).まったくもって役に立ちません.

はてなブログは多くの点で非常に使いやすく良いサービスだと思っていますが,この機能だけはどうも気に入りません.

3つの停止方法

このキーワード自動リンクを忌々しく思っている人間は私だけではないようで,インターネットで調べるとこれを停止する(不可視化する)方法がいくつか見つかります.この節ではそれぞれの方法のメリットとデメリットを見ていくことにします.

1. はてなブログProを契約する

最初に紹介するのが,いわゆる「正攻法」です.はてなブログの運営者が,有料サービスのはてなブログProでは「キーワード自動リンクオフ」のオプションを用意してくれています.おそらく,これが一番楽で,かつ他の要素とのトレードオフなしに記事からキーワード自動リンクオフを放逐する方法でしょう.

しかし,この方法には少なくとも問題が2点あります.その1つ目がこれです.

はてなブログProにお申し込みいただいてもお申し込み前に投稿された記事に関してはキーワードリンクは無効になりません

契約しても,過去記事に遡ってまではそのオプションを適用してくれないようです.契約後に再投稿を行えば解決しますが,手間がかかるでしょう.

2つ目の問題点は,キーワード自動リンクをオフにすることだけが目的とすると,月額980円というのが端的に「高すぎる」という点です.はてなブログProのサービスにおける「キーワード自動リンクオフ」オプションはおそらく副次的な要素に過ぎず,これだけをもって契約するのは(少なくとも私のようなしがない学生にとっては)現実的でありません.

したがって,この方法は他にもはてなブログProに契約することの利点を感じている人間にとっては最も有効な手段だろうと考えられますが,そうでない場合にはお金もかかる上に労力もかかるため,必ずしも最適解とは言えなそうです.

2. CSSで非表示にする

2つ目の方法はCSSを用いてキーワード自動リンクを無理やり非表示にする方法です.詳しいやり方などは下記ブログを参照するといいでしょう.

はてなブログの自動で勝手につくキーワード下線とリンクを消す - AIUEO Lab2

しかし,この方法には別の大きなデメリットがあります.

このCSSははてなブログからキーワードリンクを削除しているのではなく、非表示にするための制御です。 そのためHTML上ではリンクは残っているんです。
本来表示されるはずのものが表示されない。これはSEO上のデメリットです。

隠しリンクは,SEO的にかなりのリスクがあります *1 .無料で実現可能かつ手軽であるというのがこの方法のメリットですが,その代償はかなり大きいと言えそうです.

3. 自動リンク停止構文を用いて停止する

最後に紹介するのが,当ブログで(開設時から)使用している方法です.詳しいやり方などは次節以降で解説します.

この方法では,自動リンク停止記法を多用します.これは2つの[]で挟んだ部分について,キーワードやはてな記法などによる自動リンクを停止するというものです.自動リンク停止記法は,はてな記法の一種ですが,「はてな記法モード」のみならず「見たままモード」や「Markdownモード」でも利用することができます *2

この方法のほとんど唯一のデメリットは,「作業が面倒」ということです.次節以降で詳しく説明しますが,自動リンク停止記法は結構厄介な存在で,適切に配置しないとうまく機能しません.そのため,自動リンク停止記法をブログ記事のキーワード自動リンクが貼られる可能性のある場所全体に配置するのは結構骨の折れる作業となります.

気難しい自動リンク停止記法

自動リンク停止記法がキーワード自動リンクを停止できるのであれば,[]を記事の最初と最後に置くだけでいいのではないかと期待するのですが,話はそんなに簡単ではありません.

はてなのヘルプにも説明があるように

  • 行をまたいでの使用
  • 他の一部記法やHTMLタグとの併用

はできません.

「他の一部記法(HTMLタグ)」というのは,例えばMarkdownモードを使用する場合は以下のようなものが該当します.

  • リンクを生成するもの(リンク構文)
  • 行頭でないと使用できないもの(見出し,引用構文,箇条書き etc.)
  • 行末でないと使用できないもの(改行構文)
  • その他(TeX構文,インラインソースコード etc.)

したがって,目指すキーワード自動リンクのないブログ記事を作成するためには,これらの構文が登場する場合にはその部分を避けるように[]を挿入してやらないといけません.

作業を自動化する

言うまでもなく,前節で説明した作業を手動で行うのはかなり手間がかかります.そこで,こうした一連の「自動リンク停止記法挿入作業」を自動化するためのRubyスクリプトを書きました.ただし,利用できるのはMarkdownで原稿を作成した場合に限られ,さらに以下の制約が加わります.

  • TeX構文は [tex: \hoge %] のように終了直前に % をおく必要がある
  • 表組みを使用する場合,行頭・行末の | を省略できない

また,はてなブログで使用可能なすべてのMarkdown記法が使えるわけではありません.はてなブログで高速に記事を書けるMarkdown記法チートシートに掲載されているものと私が普段よく使用する記法に対応しています.

ここで,このスクリプトについてもう少し詳しく説明しておきます.

なお,以下に掲載するスクリプトは説明用のものなので,単体では動作しない上,最新版とは異なる可能性があります.プログラムの最新版はGitHubに上げてあるものです.

# ad_nolink.rb

in_source, in_tex = false, false

file = File.open($outputfile, "r")
    buffer = ""
    file.each_line do |line|
        # ソースコードモード
        if in_source == true
            if /^```/ === line
                in_source = false
            end
            buffer += line
        # TeXモード
        elsif in_tex == true
            if /%\]/ === line
                line.gsub!('%]', ']')
                in_tex = false
            end
            buffer += line
        # 通常モード
        else
            # ソースコードモードへ移行
            if /^```/ === line
                in_source = true
                buffer += line
                next
            end
            # TeXモードへ移行
            if /^\[tex:/ === line && !(/%\]/ === line)
                in_tex = true
                buffer += line
                next
            end
            # インラインソースコード(中身を回収)
            source_buffer = []
            line.gsub!(/`(.+?)`/) do
                source_buffer << $1
                '[]``[]'
            end
            # リンク構文
            line.gsub!(/[^!]\[.+?\]\(.+?\)/){|str| str.slice!(0,1) + '[]' + str + '[]'}
            # 引用構文
            line.gsub!(/^>\s/, '[]> []')
            # 脚注構文
            line.gsub!('((', '[](([]')
            line.gsub!('))', '[]))[]')
            # TeX構文
            line.gsub!('[tex:', '[][tex:')
            line.gsub!('%]', '][]')
            # 見出し
            if /^\#/ === line
                line.gsub!("#\ ", "#\ \[\]")
                line.gsub!("\n", "[]\n")
            end
            # enumerate構文
            if /^\s*\d+?\.\s/ === line
                line.gsub!('. ', '. []')
                line.gsub!("\n", "[]\n")
            end
            # itemize構文
            if /^\s*[*+-]\s/ === line
                line.gsub!(/[*+-]\s/){|str| str + '[]'}
                line.gsub!("\n", "[]\n")
            end
            # 表組み
            if /^\|.+\|$/ === line
                line.gsub!('|', '[]|[]')
                line.gsub!('|[]-', '|-')
                line.gsub!('|[]:', '|:')
                line.gsub!('-[]|', '-|')
                line.gsub!(':[]|', ':|')
            end
            # 画像キャプション
            if /^<figcaption>/ === line
                line.gsub!('<figcaption>', '<figcaption>[]')
                line.gsub!('</figcaption>', '[]</figcaption>')
            end
            # 行頭行末(見出し,箇条書き,HTMLタグのみ,水平線の行を除く)
            unless /^\#|^\s*[*+-]\s|^\s*\d+?\.\s|^<.+>$|^[*-_]{3,}$/ === line
                line.gsub!("\n", "")
                line.gsub!(line, '[]' + line + '[]' + "\n")
            end
            # 改行構文
            line.gsub!(/\ \ \[\]$/, '[]  ')
            # 二重[]の除去
            line.gsub!('[][]', '')
            # インラインソースコードを復元
            line.gsub!('``'){ '`' + source_buffer.shift + '`' }
            # 書き出し
            buffer += line
        end
    end
file = File.open($outputfile, "w")
    file.write(buffer)
file.close()

基本的には,行ごとに正規表現によるパターンマッチと置換処理を行うことによって自動リンク停止記法の挿入を実現しています.ただし,連続する自動リンク停止記法[][]が生じた場合は(無意味なので)除去しています.

技術的に注意が必要であったのは,ソースコードやTeXに関する部分です.これらの構文の内部には,一切の自動リンク停止記法挿入を行ないたくありません.そこで,以下のような措置をとっています.

まず,複数行のソースコード構文やTeX構文はそれぞれ開始行以降でソースコードモードとTeXモードに切り替わることで,それぞれの構文の終了行まで置換処理を行わないようにしています.

また,インラインなソースコードについては,その中身を置換処理開始前に一旦source_bufferという配列内に退避させておくことで,自動リンク停止記法が付加されることを防止しています.

なお,このスクリプトはソースコードやTeXに関する部分以外はかなり単純なので,ほんの少し手を加えるだけで簡単に対応する記法を増やすことができます.利用者各自がよく使用する記法に対応できるよう適宜改変して頂いて構いません.

まとめ

はてなブログのキーワード自動リンクの問題は些細なようで,見た目の上ではそれなりに重要な問題です.ところが,その無効化にはそれなりの代償が必要となります.

本記事中ではこれを停止するための方法を3つ紹介しました.このうち,3つ目の方法は(普通にやると)かなり手間がかかるためか他ではほとんど紹介されてこなかったようです.しかし,作業を自動化することによってその手間は大幅に削減することができます.もちろん,「原稿をスクリプトにかける」という一手間が投稿の度に必要となることは依然デメリットになるかと思います.それでも,自動化によって他の2つの方法と並ぶ3つ目の選択肢に挙げられる方法となったのではないでしょうか.

はてなブログProの契約は敷居が高いと感じられ,SEO的にも打撃を受けたくはないが,はてなブログを美しい状態に保ちたいという方は,ぜひこの方法の採用を検討してみてください.

*1:参考:隠しリンクとは? - ブラックハットSEO大全#06

*2:編集モードについては,はてなブログのヘルプを参照してください.

広告を非表示にする