【Blogger】画像コードを置換するための正規表現集
Blogger の編集画面から投稿やページに画像を挿入すると、画像コードが以下のような img
要素が div.separator
と a
要素に囲まれた形で出力されます(画像 URL の一部を省略済み)。
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/.../.../s1200/image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1200" height="168" src="https://blogger.googleusercontent.com/img/b/.../.../s320/image.png" width="320" /></a></div>
もちろんこのコードをそのまま使ってもいいのですが、個人的にはシンプルなコードが好きなので、手作業で不要な要素や属性を削除して使っていました。
ただ、挿入する画像が多くなると手作業にも限界があります。幸い Blogger の投稿画面には置換機能があるので、正規表現を使えば画像コードの一括置換が行えそうです。
そこで本記事では、Blogger において画像コードの置換に使えそうな正規表現をまとめてみました。
Blogger における正規表現の使用方法
Blogger の投稿・ページの編集画面において、次項より紹介する正規表現を用いた画像コードの置換方法を説明します。
まず、投稿・ページの編集画面でいつも通り画像をアップロードし、投稿に画像コードを挿入します。この操作は HTML ビュー と 作成ビューどちらで行っても大丈夫ですが、画像挿入後はなるべく画像コードに触らないようにしてください。
作成ビューをお使いの方は HTML ビューに変更し、エディタの右上に表示されている「置換」ボタンをクリックします。

「Replace:」に正規表現(検索文字列)を両端のスラッシュ込みで入力し、Enter を押します。

「With:」に置換文字列を入力し、Enter を押します。

「Yes」(選択された文字列を置換する)、「No」(選択された文字列を置換しない)、「All」(一括置換)、「Stop」(検索終了)のボタンが表示されるので、「Yes」か「All」をクリックすると画像コードが置換されます。

この記事で紹介する正規表現がどのように機能するのか確認できるツールを用意しました。以下のページ内リンクからツールに飛べます💁
要素を削除・追加する正規表現
画像コード内の HTML 要素を削除、追加するための正規表現集です。
本記事の冒頭で挙げたような、div.separator
で囲まれた画像コードを対象としています。
画像を一括で挿入したときに画像コード間に改行がないのが気になったので、置換文字列の末尾に \n
を付けて改行するようにしています。いらない方はこの部分を削除してください。
また、作成ビューで画像を挿入した場合デフォルトの状態だと alt
属性がないので、適宜追加してください。
div を削除
いちばん外側の div.separator
を削除します。a
要素はそのままなので、Blogger 標準のライトボックスは動作します。
/<div class=["']separator["'].+?>(<a.+?><img.+?\/><\/a>)<\/div>/
$1\n
a を削除
a
要素を削除します。この場合、Blogger 標準のライトボックスは動作しません。
/(<div class=["']separator["'].+?>)<a.+?>(<img.+?\/>)<\/a>(<\/div>)/
$1$2$3\n
div と a を削除
div.separator
と a
要素を削除し、内側のimg
要素のみを残します。こちらも、Blogger 標準のライトボックスは動作しません。
/<div class=["']separator["'].+?><a.+?>(<img.+?\/>)<\/a><\/div>/
$1\n
figure と figcaption を追加(キャプション付き画像)
div.separator
と a
要素を削除し、新たにfigure
要素と figcaption
要素を追加します。画像にキャプション(説明)を付けたいときにおすすめです。
/<div class=["']separator["'].+?><a.+?>(<img.+?\/>)<\/a><\/div>/
<figure>\n $1\n <figcaption>キャプション</figcaption>\n</figure>\n
picture と source を追加(WebP 対応)
div.separator
と a
要素を削除し、新たにpicture
要素と source
要素を追加します。
/<div class=["']separator["'].+?><a.+?><img\s(.*?)src=["'](.+?\/[swh]\d{1,4}.*?)(\/.+?)["']\s*(.*?)\s*\/><\/a><\/div>/
<picture>\n <source srcset="$2-rw-e365$3" type="image/webp"/>\n <img loading="lazy" $1 src="$2-e365$3" $4/>\n</picture>\n
source
要素の srcset
属性に WebP 化とキャッシュの有効期限の変更を行った URL を埋め込んでいます。また、img
タグでも画像 URL に対してキャッシュの有効期限の変更を行い、遅延読み込みのコード loading="lazy"
を追加しました。
WebP 変換の画像パラメータ -rw
については、以下の記事で解説されています。
キャッシュの有効期限を変更する画像パラメータ -e*
(*
は任意の数字)については、以下の記事で解説しています。
figure, figcaption, picture, source を追加(キャプション付き画像 + WebP 対応)
前述の「figure と figcaption を追加」と「picture と source を追加」の合わせ技です。
/<div class=["']separator["'].+?><a.+?><img\s(.*?)src=["'](.+?\/[swh]\d{1,4}.*?)(\/.+?)["']\s*(.*?)\s*\/><\/a><\/div>/
<figure>\n <picture>\n <source srcset="$2-rw-e365$3" type="image/webp"/>\n <img loading="lazy" $1 src="$2-e365$3" $4/>\n </picture>\n <figcaption>キャプション</figcaption>\n</figure>\n
属性を削除する正規表現
HTML 要素内の属性を削除するための正規表現集です。置換文字列はなにも入力しないでください。
こちらの正規表現は画像コード以外の部分も変換されるおそれがあるため(筆者の正規表現偏差値が低いせいですすみません)、一括置換ではなく様子を見ながらの置換をおすすめします。
div の style を削除
div.separator
の style
属性を削除します。
/(?<=<div class=["']separator["'])\sstyle=["'].*?["'](?=.*?>)/
Blogger の標準 CSS に div.separator
への指定箇所があるので、とりあえず class
属性は残して style
属性だけを消してみました。
a の style と imageanchor を削除
a
の style
属性と、作成モードで画像を挿入したときのみ付与される imageanchor
属性を削除します。
/(?<=<a\s.*?)\s(style|imageanchor)=["'].+?["'](?=.*?>)/
この imageanchor
属性、調べてもどういう用途で使われているのかいまいちわからないんですが(どうやら画像の表示位置を示すっぽい?)、Nu Html Checker に掛けると以下のようなエラーが出るので消しても大丈夫だと思います。
Attribute imageanchor not allowed on element a at this point.
(和訳:現時点では、a 要素では imageanchor 属性を使用できません。)
ちなみに imageanchor
属性だけを消したい場合は、上記の検索文字列の (style|imageanchor)
の部分を imageanchor
に書き換えればオッケーです。
img の border と data-original-width/height を削除
img
の border
属性と、data-original-width
属性および data-original-height
属性を削除します。
/(?<=<img.*?)\s(border|data-original-(width|height))=["'].+?["'](?=.*?\/>)/
border
属性は Nu Html Checker に掛けると以下のように警告が出るように、すでに廃止されている属性なので削除推奨です。
The border attribute is obsolete. Consider specifying img { border: 0; } in CSS instead.
(和訳:border 属性は廃止されました。代わりに CSS で img { border: 0; } を指定することを検討してください。)
data-original-width
属性と data-original-height
属性に関しては、以下のスレッドによると「特にレスポンシブ画像を生成する際に、Blogger の内部システムが画像のオリジナルサイズを把握するために使われる」そうです。
- What is the usage of data-original-width data-original-height in img tag - Blogger Community(和訳:img タグの data-original-width と data-original-height の使い方は?)
画像表示の最適化に一役買ってるなら残しておいてもいいのかなと思いますが、筆者はなるべくコードを短くしたい人間なので容赦なく消します笑
ちなみに border
属性だけを消したい場合は、上記の検索文字列の (border|data-original-(width|height))
の部分を border
に書き換えればオッケーです。
画像コード用正規表現確認ツール
ここまで紹介してきた正規表現で画像コードがどのように置換されるのか確認できるツールを作りました。コピー機能が付いているので、画像コード変換ツールとしても使えます🙆
「変換前のコード」のテキストエリアに画像コードを貼り付け(デフォルトでダミーコードを入力してあります)、置換オプションを選択後、「変換」ボタンをクリックしてください。「変換後のコード」のテキストエリアに、正規表現で置換された画像コードが出力されます。
選択したオプションを解除したい場合は、「選択解除」ボタンをクリックしてください。
「コードをコピー」ボタンで置換後のコードがコピーできます。コピー機能に Clipboard API を利用しているため、Internet Explorer には非対応です。IE をお使いの方はコードを全選択してコピーしてください。
「元に戻す」ボタンをクリックすると、「変換前のコード」のテキストエリアはダミーコードが入力された状態に、「変換後のコード」のテキストエリアは空になります。間違えて押さないようにお気を付けください。
以下が、確認ツールの HTML と JavaScript です。CSS は当ブログ独自仕様すぎて参考にならないと思うので割愛しています。
<form class="replace-tool">
<label>変換前のコード:<br><textarea id="inputCode" placeholder="ここに画像コードを入力"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/.../.../s1200/image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1200" height="168" src="https://blogger.googleusercontent.com/img/b/.../.../s320/image.png" width="320" /></a></div></textarea></label>
<label>変換後のコード:<br><textarea id="outputCode" placeholder="変換されたコードがここに表示されます"></textarea></label>
<div class="replace-menu" data-title="要素を削除・追加">
<label><input type="radio" name="tag" value="option1"/> div を削除</label>
<label><input type="radio" name="tag" value="option2"/> a を削除</label>
<label><input type="radio" name="tag" value="option3"/> div と a を削除</label>
<label><input type="radio" name="tag" value="option4"/> picture と source を追加</label>
<label><input type="radio" name="tag" value="option5"/> figure と figcaption を追加</label>
<label><input type="radio" name="tag" value="option6"/> figure, figcaption, picture, source を追加</label>
</div>
<div class="replace-menu" data-title="属性を削除">
<label><input type="checkbox" name="attr" value="option1"/> div の style を削除</label>
<label><input type="checkbox" name="attr" value="option2"/> a の style と imageanchor を削除</label>
<label><input type="checkbox" name="attr" value="option3"/> img の border と data-original-width/height を削除</label>
</div>
<button type="button" onclick="replaceCode()">変換</button>
<button type="button" onclick="deselectOptions()">選択解除</button>
<button type="button" onclick="copyReplacedCode()">コードをコピー</button>
<button type="reset">元に戻す</button>
</form>
<script>
function replaceCode() {
const inputArea = document.querySelector('.replace-tool #inputCode');
const outputArea = document.querySelector('.replace-tool #outputCode');
let outputCode = inputArea.value;
const selectedTag = document.querySelector('.replace-tool input[name="tag"]:checked');
if (selectedTag) {
switch (selectedTag.value) {
case 'option1':
outputCode = outputCode.replace(/<div class=["']separator["'].+?>(<a.+?><img.+?\/><\/a>)<\/div>/g, '$1\n');
break;
case 'option2':
outputCode = outputCode.replace(/(<div class=["']separator["'].+?>)<a.+?>(<img.+?\/>)<\/a>(<\/div>)/g, '$1$2$3\n');
break;
case 'option3':
outputCode = outputCode.replace(/<div class=["']separator["'].+?><a.+?>(<img.+?\/>)<\/a><\/div>/g, '$1\n');
break;
case 'option4':
outputCode = outputCode.replace(/<div class=["']separator["'].+?><a.+?><img\s(.*?)src=["'](.+?\/[swh]\d{1,4}.*?)(\/.+?)["']\s*(.*?)\s*\/><\/a><\/div>/g, '<picture>\n <source srcset="$2-rw-e365$3" type="image/webp"/>\n <img loading="lazy" $1 src="$2-e365$3" $4/>\n</picture>\n');
break;
case 'option5':
outputCode = outputCode.replace(/<div class=["']separator["'].+?><a.+?>(<img.+?\/>)<\/a><\/div>/g, '<figure>\n $1\n <figcaption>キャプション</figcaption>\n</figure>\n');
break;
case 'option6':
outputCode = outputCode.replace(/<div class=["']separator["'].+?><a.+?><img\s(.*?)src=["'](.+?\/[swh]\d{1,4}.*?)(\/.+?)["']\s*(.*?)\s*\/><\/a><\/div>/g, '<figure>\n <picture>\n <source srcset="$2-rw-e365$3" type="image/webp"/>\n <img loading="lazy" $1 src="$2-e365$3" $4/>\n </picture>\n <figcaption>キャプション</figcaption>\n</figure>\n');
break;
}
}
const selectedAttr = document.querySelectorAll('.replace-tool input[name="attr"]:checked');
selectedAttr.forEach(a => {
switch (a.value) {
case 'option1':
outputCode = outputCode.replace(/(?<=<div class=["']separator["'])\sstyle=["'].*?["'](?=.*?>)/g, '');
break;
case 'option2':
outputCode = outputCode.replace(/(?<=<a\s.*?)\s(style|imageanchor)=["'].+?["'](?=.*?>)/g, '');
break;
case 'option3':
outputCode = outputCode.replace(/(?<=<img.*?)\s(border|data-original-(width|height))=["'].+?["'](?=.*?\/>)/g, '');
break;
}
})
outputArea.value = outputCode
}
function deselectOptions() {
document.querySelectorAll('.replace-tool input[name]:checked').forEach(c => {
c.checked = false
})
}
function copyReplacedCode() {
const outputCode = document.querySelector('.replace-tool #outputCode').value;
navigator.clipboard.writeCode(outputCode).then(() => {
alert('コピーしました')
}).catch(() => {
alert('コピーに失敗しました')
})
}
</script>
ChatGPT に作ってもらったコードにいろいろと手を加えてみました。switch
文が使われてる部分は、自力でコード書いたら十中八九 if
文にしてしまうと思うので勉強になりました。
あとがき
Blogger のデフォルトの画像コードに使える正規表現をまとめました。置換後のコードの確認用に画像コード変換ツールも作ってみました。
前述の通り正規表現がだいぶ苦手なもので、もしかしたら掲載している文字列に間違いがあるかもしれません。その場合は本記事のコメント欄で教えていただけると助かります。
画像コード置換関連で、他にもいい感じの正規表現を考えついたら随時追加していこうと思います。