いっしきまさひこBLOG

AI・機械学習やAIコーディングを中心に、試したことや気づきをまとめている個人ブログです。一色政彦。

SmartURLs ― 複数URLをスマートにコピー&オープンできる拡張機能

調べものやライティング、コーディング、編集作業など、オンラインで仕事をしていると、いつの間にかブラウザのタブが大量に開いてしまうことがあります。
それらのURLをまとめてコピーしたり、管理したりするのは意外と面倒ですよね。

そこで私は、複数のURLをすばやく・柔軟に・安全に扱える軽量Chrome拡張機能SmartURLs(スマート・ユアールエルズ)を開発しました。🚀

SmartURLs Screenshot

💡 SmartURLsでできること

SmartURLsは、日常的によくある2つの作業をぐっと簡単にします。

1. 開いているタブのURLを一括コピー

現在のウィンドウ、またはすべてのウィンドウのURLを一瞬で取得し、以下の形式で書き出せます。

  • Markdown
  • HTML
  • JSON
  • TSV(タブ区切り)
  • あるいは独自のテンプレート形式

さらに、ピン留めタブを除外したり、重複を省いたり、HTTPSのみを抽出したりといった細かいフィルタリングにも対応しています。

2. 複数のURLを一括で開く

テキスト内に含まれるURL(Markdown、HTML、プレーンテキストなど)をペーストすれば、すべてのリンクをワンクリックで開けます。
Smart Parserが自動で形式を判別してくれるので、面倒な設定は不要です。

💭 開発のきっかけ

私はWebライター兼エンジニアとして、日々多くのページを調べたり、URLを集めたりしています。
その中で、「自分の使い方にぴったり合う拡張機能がなかなか見つからない」と感じていました。

そこで、自分が本当に欲しかったツールを作ることにしたのです。

目指したのは、こんな拡張機能です。

  • ✨ 軽快でシンプルに動く
  • 🔒 通信を一切しない(完全ローカル処理)
  • 🌍 英語・日本語など多言語対応
  • 🔧 オープンソースで公開

🎨 シンプルで見やすいUI

SmartURLsは、ライト/ダーク/システムテーマに対応したレスポンシブなポップアップUIを採用しています。
設定はChrome Storageに自動保存され、初期設定も不要です。

SmartURLs Popup (Dark)

SmartURLs Popup (Light)

⚙️ 主な特徴

  • 🌐 複数URLをワンクリックでコピー&オープン
  • ✨ 出力テンプレートをカスタマイズ可能
  • 🌓 ライト/ダーク/システムテーマ対応
  • 🗣 16言語対応
  • 🔒 完全オフライン動作(データは外部に送信されません)
  • 🔓 オープンソース(Apache License 2.0)

🆕 v1.3.0 の新機能

SmartURLs は キーボードショートカットに対応しました。 これにより、これまでよりさらに素早くコピー/オープン操作が行えます。

  • URLをコピー: Ctrl + Shift + U
  • URLをオープン: Ctrl + Shift + V

ショートカットは以下から自由に変更できます: chrome://extensions/shortcuts

📦 インストール方法

Chrome ウェブストアからインストール
👉 SmartURLs – Copy & Open URLs

GitHub から手動インストール
👉 isshiki/SmartURLs on GitHub

💬 おわりに

SmartURLsは「なんでもできる万能ツール」を目指していません。
その代わり、「リンクを扱う手間をなくすこと」だけに集中しています。

URLのコピーや一括オープンを、もっとスマートに、もっとストレスなく。

SmartURLs は、あなたの作業を少しだけ軽くしてくれる小さな相棒になるかもしれません。

追伸Tips:ショートカットキーを設定しよう

デフォルトでも、空いていそうなキーの組み合わせにショートカットキーが設定されています。

ただ、よく使うショートカットキーをキーボードの左下付近に集めておくと、片手で操作しやすくなり、かなり快適です。私は以下のように設定しています。

ショートカットキーの設定例

上記はWindowsでの設定例ですが、Macでも同じような考え方で設定しています。

ただし、注意点があります。Chromeでは、Ctrl + Shift + C キーがChrome DevTools、いわゆるF12開発者ツールの[要素]パネルを開くショートカットキーとして使われています。

developer.chrome.com

DevToolsのショートカットキーは、設定から変更できないようです。そのため、同じキーを別の機能に割り当てると、Chrome DevToolsのショートカットを上書きしてしまいます。

私の場合、[要素]パネルを使うときは手動でF12開発者ツールを開き、左上の要素選択ボタンから操作しているため、特に困っていません。

ただし、Ctrl + Shift + C キーを頻繁に使う人にとっては不便になる可能性があります。必要に応じて、別のキーの組み合わせに変更してください。

SmartURLs: A Smarter Way to Copy and Open URLs

When you work online—researching, writing, coding, or editing—you probably have a browser full of tabs.
Copying and managing those URLs can be a pain.

That’s why I built SmartURLs, a lightweight Chrome extension that makes copying and opening multiple URLs fast, flexible, and private. 🚀

SmartURLs Screenshot

💡 What SmartURLs Does

SmartURLs simplifies two everyday tasks:

1. Copy all open tabs instantly

Export your current or all-window tabs in multiple formats:

  • Markdown
  • HTML
  • JSON
  • TSV
  • Or your own custom text template

You can even filter results—skip pinned tabs, remove duplicates, or include only HTTPS links.

2. Open multiple URLs at once

Paste any text containing URLs (Markdown, HTML, plain text, etc.) and open them all in one click.
Smart Parser automatically detects the format so you don’t have to.

💭 Why I Created It

As a web writer and developer, I often needed to collect, copy, and reopen many URLs quickly.
But I couldn’t find an existing extension that perfectly fit my workflow — either too complex, too limited, or just not quite right for everyday use.

So I decided to build the tool I truly wanted to use myself.

Here’s what I aimed for:

  • ✨ Fast and lightweight
  • 🔒 100% local (no network requests)
  • 🌍 Multilingual (English, Japanese, and more)
  • 🔧Fully open-source

🎨 Designed for Clarity

SmartURLs has a clean, responsive popup UI with Light/Dark/System themes.
Settings are saved automatically via Chrome Storage — no setup required.

SmartURLs Popup (Dark)

SmartURLs Popup (Light)

⚙️ Key Features

  • 🌐 Copy or open multiple URLs in one click
  • ✨ Custom export templates
  • 🌓 Light / Dark / System themes
  • 🗣 16 languages supported
  • 🔒 Works completely offline — your data never leaves the browser
  • 🔓 Open-source (Apache License 2.0)

🆕 New in v1.3.0

SmartURLs now supports keyboard shortcuts for even faster workflows.

  • Copy URLs: Ctrl + Shift + U
  • Open URLs: Ctrl + Shift + V

You can customize or manage these shortcuts anytime from: chrome://extensions/shortcuts

📦 Installation

From the Chrome Web Store:
👉 SmartURLs – Copy & Open URLs

From GitHub (Manual Installation):
👉 isshiki/SmartURLs on GitHub

💬 Final Thoughts

SmartURLs doesn’t try to be an all-in-one manager.
It focuses on what matters: making link handling effortless.

If you ever wished copying or reopening URLs could be just one click away,
SmartURLs might become one of those small tools you can’t work without.

PromptLinker ― ChatGPT・Claude・Perplexityに“一発で飛べる”プロンプトリンク生成ツール

プロンプトを入力してリンクを生成する画面

AIに質問するとき、毎回ブラウザを開いて、テキストをコピペして……という手間を感じたことはありませんか? PromptLinker は、そんな煩わしさを一瞬で解消するシンプルなWebツールです。 入力したプロンプトを自動的にエンコードして、ChatGPT/Claude/Perplexity へ直接飛べるリンクを生成します。

機能概要

  • 入力した文章を RFC 3986 準拠 で自動エンコード
  • ChatGPT/Claude/Perplexity に対応(3サービス同時生成)
  • 改行(%0A)も正確に保持
  • クライアントサイドで完結(サーバ不要・ログも残らない)

使い方

  1. PromptLinker(Web版) にアクセス
  2. テキストエリアにプロンプトを入力
  3. 「生成する」ボタン、または Shift + Enter でリンクを作成
  4. 表示された各サービスのボタンからワンクリックで遷移

シンプルな仕組みですが、一度使うともう戻れない快適さがあります。

仕組みの概要

PromptLinkerは、入力されたテキストをURLクエリとして渡すために、 JavaScriptの標準関数 encodeURIComponent() を使って RFC 3986形式でエンコード しています。

  • 英数字と - . _ ~ はそのまま使用
  • 改行は %0A に変換
  • それ以外の文字はすべて安全にエスケープ

この形式で生成されたURLを、それぞれのAIサービスに埋め込みます。 なお、Geminiについては現時点でURLクエリによるプロンプト渡しができないため、対応を見送っています。

導入方法

ブラウザだけで動作するため、インストールは不要です。 以下のURLにアクセスすればすぐに利用できます。

https://isshiki.github.io/PromptLinker/

ローカルで使いたい場合は、GitHubリポジトリから index.html をダウンロードして、 任意の場所で開くだけで動作します。

開発メモ

  • 構成:HTML/CSS/JavaScript のみ(単一ファイル構成)
  • デプロイ:GitHub Pagesで main ブランチのルートを公開すれば利用可能
  • ソースコード:GitHubリポジトリはこちら

まとめ

AIを使う頻度が増えるほど、「プロンプトを渡すまでの数秒」が意外とストレスになります。 PromptLinkerは、その数秒を短縮する小さなツールですが、毎日の作業効率を確実に変えてくれます。

ChatGPTやClaude、Perplexityを日常的に使う人なら、ブックマークしておいて損はありません。

Gartner風「ハイプ・サイクル」曲線をPythonで描く ― hype-cycle-curve 公開

hype_cycle_with_labels.svg

新しいAI技術やトレンドを可視化する際によく登場する「ハイプ・サイクル(Hype Cycle)」。 あのガートナーのグラフを、自分で描けたら便利だと思ったことはありませんか?

そんな方のために、Pythonだけで簡単にハイプ・サイクル曲線を描けるツールを作りました。 👉 GitHub: isshiki/hype-cycle-curve

🎨 特徴

  • CSVデータ(x,y)からスムーズな曲線を自動生成
  • フェーズ分割の縦線(期待のピーク、幻滅期など)を追加可能
  • マーカーやラベルを自由にカスタマイズ(色・サイズ・位置など)
  • 日本語フォント対応(matplotlib-fontja
  • すぐ使えるSVG/PNGサンプルを同梱

💡 使い方はシンプル

uv run python scripts/render_hype_curve.py \
  --csv data/hype_cycle_curve.csv \
  --out out/hype_cycle_with_labels.svg \
  --phase-lines

1行でハイプ・サイクルのSVGが生成されます。 オプションを追加すれば、マーカーやラベルも自由自在です。

hype_cycle_vivid.svg

📦 GitHub リポジトリ

ソースコード、サンプル画像、README(英語版)はすべてこちら:

👉 https://github.com/isshiki/hype-cycle-curve

💬 こんな使い方におすすめ

  • AI技術や製品の「期待値の推移」を可視化
  • カンファレンスや資料での技術マッピング
  • ブログやレポートの挿絵に

Pythonユーザーなら uv sync だけで環境構築が完了します。 技術トレンドの可視化に、ぜひ使ってみてください。

Visualize the AI Trend ― Python Hype Cycle Curve Generator Released

hype_cycle_with_labels.svg

Ever wanted to draw a Gartner-style Hype Cycle graph by yourself — just like those you see in tech reports? Now you can, with this small Python tool.

👉 GitHub: isshiki/hype-cycle-curve

✨ Features

  • Generates smooth hype-cycle curves from simple x,y CSV data
  • Optional vertical phase dividers (e.g. Peak of Inflated Expectations)
  • Fully customizable markers and labels
  • Supports Japanese text (matplotlib-fontja)
  • Includes ready-to-use SVG and PNG samples

⚙️ Quick Example

uv run python scripts/render_hype_curve.py \
  --csv data/hype_cycle_curve.csv \
  --out out/hype_cycle_with_labels.svg \
  --phase-lines

That’s all — it creates a smooth Hype Cycle curve instantly. Add markers and labels with flexible style options.

hype_cycle_vivid.svg

📁 Repository

All source code, sample outputs, and documentation are available here:

👉 https://github.com/isshiki/hype-cycle-curve

💡 Ideal for

  • Visualizing AI or technology hype trends
  • Presentations and technical reports
  • Blog illustrations or dashboards

Clone the repo, run uv sync, and start visualizing your own Hype Cycle in minutes. Simple, elegant, and fully customizable.

CMSサイト(動的)→S3(静的)移行を自動化! Pythonスクリプト公開中

「CMSで管理されている動的なWebサイトを静的サイトに移行したい」と考えている人向けの記事です。CMSでサイトを頻繁に更新する必要がなくなった場合や、運用コストを削減したい場合などで、静的サイトへの移行は大きなメリットをもたらします。以下では、私が実践した手法と、そのために作成したPythonスクリプトを紹介します。

課題と解決策

CMSを利用した動的サイトには以下の課題があります:

  • サーバーコストが高い
  • CMSのメンテナンスが手間

これらを解決するため、私はCMSサイトを静的化し、Amazon S3+CloudFrontでホスティングする方法を選びました。この作業を効率化するため、自作のPythonスクリプトを開発しました。

このスクリプトは、以下の機能を実現します:

  • 静的化:CMSからローカル環境にHTMLファイルを取得
  • リンク修正(オプション):内部リンクの変換や、一部HTML内容の変更
  • ホスティング設定:S3にアップロード

このあと、CloudFrontでHTTPS対応のホスティングを設定する作業は説明資料に従って進めてください。

スクリプトはGitHubで公開しています:

本スクリプトおよび資料は、現状のまま(AS IS)で提供されており、いかなる保証も行いません。本スクリプトの使用により発生したいかなる損害や問題についても、作成者は一切の責任を負いかねます。ご利用は自己責任でお願いいたします。

説明資料

詳細な手順はREADME.mdに記載しています。以下にもその内容を転載しておきます。


Dynamic Web to S3 Migration

このプロジェクトは、CMS管理のWebサイトからファイルをダウンロードし、Amazon S3にアップロードするためのPythonスクリプトを提供します。

また、アップロードした後に、Amazon S3をスタティック(静的)なWebサイトホスティングサービスとして構成し、Amazon CloudFrontによりCDNで配信されるようにし、AWS Certificate Manager(ACM)により生成し自動更新されるHTTPS用のSSL証明書を設定するまでの作業手順も、このREADME.mdファイルに掲載しています。

ただし、スクリプトはWindows環境で実行しているため、それ以外の環境での動作は保証できません。細かい調整が必要な場合は、スクリプトを修正することで対応してください。

※本スクリプトの実行は自己責任で行ってください。いかなる責任も負いません。また、本スクリプトにPR(プルリクエスト)やIssue(問題報告)を送られても、一切対応しませんので、あしからずご了承ください。

構成

  • requirements.txt: 必要なPythonパッケージのリスト。
  • config.ini: 認証情報を含む設定ファイル。
  • WebHtmlDownload.py: CMS管理のWebサイトから全てのHTMLファイルをダウンロードします。
  • AwsS3Upload.py: ダウンロードされたファイルをAmazon S3にアップロードします。

ログファイル

  • <トップのローカルフォルダ名>_download_log.txt: Webサイトからのダウンロードに関するログ。
  • <トップのローカルフォルダ名>_processed_log.txt: 処理済みのURLに関するログ。
  • <トップのローカルフォルダ名>_skipped_log.txt: スキップしたURLに関するログ。
  • <トップのローカルフォルダ名>_download_retry.txt: ダウンロードに失敗したURLに関するリトライ用のログ。
  • <S3名>_upload_log.txt: Amazon S3へのアップロードに関するログ。
  • <S3名>_compare_log.txt: WebサイトとAmazon S3の内容比較に関するログ。

<トップのローカルフォルダ名>(Webサイト管理用の名前)は、S3バケット名と同じ名前にします。例:wwwexamplecom

リトライ機能

※本プロジェクト開発者が試した限りでは、失敗が発生したことがないため、リトライ機能は実装済みですが、正常に稼働するかは検証されていません。

  • ダウンロードやアップロードに失敗したファイルは、リトライ用のファイルに記録されます。
  • 次回実行時にリトライ用のファイルを読み込み、前回失敗した処理を再試行します。成功した処理は再試行しません。
  • 全てのファイルが成功した場合、リトライ用のファイルは削除されます。

前提条件

CMS管理のWebサイトをWebサーバとして活用してダイナミックなWebページを配信していることを前提としています(※ただし、未検証ですがスタティックWebサイトでも有効ななずです)。また、Azure CDNなどでCDNとSSLの自動更新を対応している場合もカバーしています。

同名のAmazon S3バケットを以下の手順で作成しておいてください。

S3バケットを作る手順

作成時に以下の内容を指定することを前提とします。

  1. AWS リージョンは「アジアパシフィック (東京) ap-northeast-1」とします。
  2. AWSコンソールでS3の[汎用バケット]を開き、[バケットを作成]をクリックします。
  3. [バケットタイプ]は「汎用」を選択します。
  4. [バケット名]は<トップのローカルフォルダ名>(Webサイト管理用の名前)と同じ名前にします。例:wwwexamplecom
  5. [ACL無効]を選択してください。
  6. [パブリックアクセスをすべてブロック]のチェックを外してください。
  7. [バケットのバージョニング]は「有効にする」にしてください。
  8. [タグ - オプション]でキーは「Name」、値は「<任意のプロジェクト名(例:masahiko.info)>」でタグを追加してください。
  9. 他はデフォルトのまま[バケットを作成]をクリックしてください。
  10. これでS3バケットの作成は完了です。

必要なPythonパッケージ

以下のコマンドを使用して、必要なパッケージをインストールしてください。

pip install -r requirements.txt

認証情報の設定

AWSのアクセスキーの取得

AWSのアクセスキーはユーザーごとに取得します。セキュリティの問題もあるので、全ての作業が終わったら無効化もしくは削除するのがお勧めです。

  1. AWS Management Consoleにログインし、IAMサービスに移動します。
  2. 左側のメニューから[ユーザー]を選択します。
  3. 該当のユーザー名をクリックします。
  4. 上部の[セキュリティ認証情報]タブを開きます。
  5. [アクセスキーを作成]をクリックします。
  6. [ユースケース]は「ローカルコード」を選択します。
  7. [説明タグ値]は空のままで[アクセスキーを作成]をクリックします。
  8. これにより、アクセスキーIDとシークレットキーが発行されるので、確実にどこかに記述してください。

config.iniの編集

ご自身の環境に合わせて修正してください。

  • domainName: CMS管理Webサイトのドメイン名を指定します。例:www.example.com
  • sitemapUrlPath: Web検索用サイトマップへのルートからのパスを指定します。例:/sitemap.xml
  • topLocalName: トップのローカルフォルダ名(Webサイト管理用の名前)を指定します。S3バケット名と同じ名前にしてください。例:wwwexamplecom
  • indexFileName: インデックスドキュメント名(デフォルトのルートオブジェクト)を設定します。例:index.html
  • S3BucketName: 比較対象のS3バケット名を設定します。
  • AccessKeyId: AWSアクセスキーIDを設定します。
  • SecretAccessKey: AWSシークレットアクセスキーを設定します。
  • Region: AWSリージョンを設定します。

使用方法

WebHtmlDownload.pyの使用方法

(1) WebHtmlDownload.pyを実行して、CMS管理のWebサイトから全てのHTMLファイルをダウンロードします。

python WebHtmlDownload.py

※古い形式のサイトマップのスキーマ「http://www.google.com/schemas/sitemap/0.84」にしか対応していません。これ以外の場合、コードを修正する必要があります。

(2) ダウンロードされたファイルは、指定されたローカルディレクトリに保存されます。

AwsS3Upload.pyの使用方法

(1) AwsS3Upload.pyを実行して、ダウンロードされたファイルをAmazon S3にアップロードします。

python AwsS3Upload.py

(2) アップロードの成功または失敗はログファイルに記録されます。

全て成功すれば作業は完了です。

さらに、Favicon(Webサイト用のアイコン)もある場合は、適切な場所(例えば/favicon.ico)にAmazon S3のサイトでアップロードしてください。

S3バケットをスタティックなWebサイトホスティングサービスにするまでの手順

注意事項

  • パブリックアクセスを有効化する際はセキュリティに注意してください。不要なデータが公開されないように。
  • 公開したくないファイルはそもそもアップロードしない方がよいでしょう。このスクリプトではもともとWebサイトでパブリックに公開されていたオブジェクト(主にHTMLページ)のみを移行する仕様になっていますので、基本的には新たに不要なデータが公開されることはないはずです。

手順 1: 静的Webサイトホスティングを有効化

  1. AWSコンソールで対象のS3バケットを選択します。
  2. 上部メニューの[プロパティ]をクリックしてください。
  3. [静的Webサイトホスティング]セクションの[編集]をクリック。
  4. 「静的Webサイトホスティング」の「有効にする」を選択します。
  5. [ホスティングタイプ]jは、「静的ウェブサイトをホストする」を選択します。
  6. [インデックスドキュメント](例: index.htmldefault.html)を入力。
    • 必要なら[エラードキュメント](例: error.html)も入力。このファイルは基本的にバケットのルート(トップレベル)に配置してください。
  7. [変更の保存]をクリックします。

サンプルのerror.htmlファイルをこのプロジェクトに含めていますので、これをS3バケットのトップレベルにアップロードしてみてください。

手順 2: ブロックパブリックアクセスをオフにする

この作業は、作成時にオフにしていれば不要です。

  1. 上部メニューの[アクセス許可]をクリック。
  2. [ブロックパブリックアクセス (バケット設定)]セクションの[編集]をクリック。
  3. すべてのチェックボックスをオフにします。
  4. 保存します。
  5. 注意: この設定変更により、バケットがパブリックにアクセス可能になるリスクがあります。次のポリシー設定を適切に行いましょう。

手順 3: バケットポリシーを設定

S3バケットをパブリックにアクセス可能にするため、バケットポリシーを記載します。

以下は、特定のS3バケット(例: example-bucket)内のすべてのオブジェクトをパブリックにするポリシーです。arn:aws:s3:::example-bucketの部分は「バケット ARN」と呼ばれますが、編集画面上でコピーできます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
  1. 引き続き[アクセス許可]にある[バケットポリシー]セクションの[編集]をクリック。
  2. 上記のJSONコードを貼り付けます(example-bucketを実際のバケット名に変更)。
  3. 保存します。

手順 4: オブジェクト所有者を確認

S3バケットの[アクセス許可]で[オブジェクト所有者]が「バケット所有者の強制」となっている場合、ACL(アクセスコントロールリスト)は無効になっています。つまり、このバケット内のすべてのオブジェクトは、このアカウントによって所有されます。このバケットとそのオブジェクトへのアクセスは、ポリシーのみを使用して指定されます。

このプロジェクトでは、ACLが無効であることを前提としています。ACLが有効な場合、バケットポリシーを設定しても、オブジェクト(ファイル)がパブリックでない場合があります。

手順 5: WebサイトのURLにアクセス

スタティックWebサイトのURLは、以下の形式になります。

http://{バケット名}.s3-website-{リージョン}.amazonaws.com
http://wwwexamplecom.s3-website-ap-northeast-1.amazonaws.com
  1. 対象のS3バケットの上部メニューの[プロパティ]をクリックしてください。
  2. 一番下の[静的ウェブサイトホスティング]にある「バケットウェブサイトエンドポイント」のURLを開いてみてください。個別のオブジェクトにアクセスできるかは後で確認します。
  3. 上部メニューの[オブジェクト]から任意のオブジェクトを開いてください。
  4. 上部メニューの[プロパティ]を開き、[オブジェクトの概要]の[オブジェクト URL]を開いて、実際にWebアクセスできるかを確認してください。
  5. これによりHTMLページや画像などが正常に表示されれば、S3のスタティックなWebサイトの公開は完了です。

S3バケットのサイトがCDN(カスタムドメインSSL証明書あり)で配信されるまでの手順

Amazon CloudFrontの手順の中で、AWS Certificate Manager(ACM)を使ってカスタムドメイン用のSSL証明書を取得するようになっています。証明書の発行時にDNS検証を選択することによって、期限切れの60日前に自動更新されます。

Amazon CloudFrontの設定手順

  1. CloudFrontディストリビューションの作成

    1. AWS Management Consoleにログインし、CloudFrontサービスに移動します。
    2. [CloudFront ディストリビューションを作成]をクリックします。
    3. [Origin domain]で、S3バケットのエンドポイントを選択し、それにより表示される[Web サイトのエンドポイントを使用]をクリックします。
      • 例: - <バケット名>.s3-website-<リージョン>.amazonaws.com
    4. [名前]は自動的に入力されます。
    5. [デフォルトのキャッシュビヘイビア]セクションで[ビューワープロトコルポリシー]を「Redirect HTTP to HTTPS」に設定します。
    6. [ウェブアプリケーションファイアウォール (WAF) ]セクションで「セキュリティ保護を有効にしないでください」を選択します。追加費用を発生させないためです。必要になったらONにすればよいと思います。
    7. [設定]セクションの[料金クラス]で、日本メインなら「北米、欧州、アジア、中東、アフリカを使用」を選択します。性能と価格のバランスがよいためです。世界中からアクセスされるなら「すべてのエッジロケーションを使用する (最高のパフォーマンス)」がよいでしょう。
    8. その下の[代替ドメイン名 (CNAME) - オプション]で、[項目を追加]をクリックして、カスタムドメイン名(例:re.masahiko.info)を入力します。
    9. その下の[Custom SSL certificate - optional]で、[証明書をリクエスト]リンクをクリックします。
      • [パブリック証明書をリクエスト]を選択して[次へ]をクリックします。
      • [完全修飾ドメイン名]にカスタムドメイン名(例:re.masahiko.info)を入力します。
      • [検証方法]は「DNS 検証 - 推奨」に必ずしてください。
      • 他はデフォルトの推奨設定のままにします。
      • リソースグループで管理しやすいように[タグ]も付けるのがお勧めです。キーは「Name」として、値は「masahiko.info」など独自のグループ名を指定します。
      • [リクエスト]をクリックします。
      • [ステータス]が「保留中の検証」となるので、検証用にDNSのCNAMEの追加が必要です。お使いのDNSの設定箇所で、[ドメイン]内の表で取得できる「CNAME名」からサブドメインまでの部分(例:_abcdef123456gh7i8j9klm01n2opq345.<subdomain>)を名前として、「CNAME値」(ドメイン名で場合によっては最後の.を除いて内容、例:_a0123bcdefghigklmnopqrst45fvwxyz.zfyfvmchrl.acm-validations.aws.)を値(正規名)として指定してください。
      • 30分もしないうちに発行済みになります。[ステータス]に「発行済み」と表示されるまで待ちます。ブラウザーでリロードすると表示が変わる場合があります。
    10. CloudFrontのディストリビューション作成画面に戻ります。
    11. [Custom SSL certificate - optional]の右端の更新ボタンをクリックした後で、先ほど作成したSSLを[Custom SSL certificate - optional]で選択します。
    12. [Default root object - optional]にルート(/)でアクセスされたときに自動表示するファイル名(例: index.htmldefault.html)を入力。
    13. [ログ配信]は必要があればオンにしてください。ただし追加費用がかかるため、私の場合はオフにしています。
    14. [ディストリビューションを作成]をクリックします。
  2. CloudFrontディストリビューションのデプロイ

    • ディストリビューションのステータスが「有効」になるまで待ちます。わたしの場合はすぐでしたが、数分かかることがあるようです。
    • ディストリビューションのステータスは、CloudFrontのトップページでも確認できます。
  3. CloudFrontディストリビューションの確認

    • CloudFrontディストリビューションの[ディストリビューションドメイン名]を使用して、S3に配置したオブジェクトのパスのWebページや画像にアクセスして、無事に表示されるのを確認します(表示されるようになるまでに数分かかります)。例: d123456abcdef8.cloudfront.net
    • [ディストリビューションドメイン名]はCDN設定で使うので、保存しておいてください。

カスタムドメインのDNS設定と確認

最後にカスタムドメインでアクセスされるように設定すれば完了です。

カスタムドメインのCNAMEの内容(ドメイン名)に[ディストリビューションドメイン名]を指定してください。[ディストリビューションドメイン名]はCloudFrontで確認できます。

念のため、依然のCNAME内容は一時的に何かに書き写してバックアップしておきましょう。

反映まで1時間ほどかかります。長い場合は72時間程度も時間がかかることがあります。反映されたかはSSL証明書をブラウザから確認すればよいでしょう。もしくは以下のコマンドで確認できます。

nslookup <カスタムドメイン名>

ここまで出来たらCMS管理のWebサイトとAzure CDNの役目も終了なので、削除しても構いません。が、トラブル回避のため、72時間ほど様子を見てからの方がよいかもしれません。

全ての作業が終わったら、AWSのアクセスキーは無効化するか、削除しておきましょう。

ライセンス

このプロジェクトはApache License 2.0の下で公開されています。詳しくはLICENSEファイルをご確認ください。

Azure Blob(Webホスティング用)→S3移行を自動化! Pythonスクリプトを公開中

2024年12月、「Azure CDN from Edgioが廃止される」という突然の通知に驚き、移行作業に追われた方も多いのではないでしょうか。私もその1人でした。Webスタティックホスティング用途で「Azure Blobストレージ+Azure CDN」を複数のサイトで利用していたため、急遽、別のCDNへの移行が必要になりました。

Azure Front Doorへの移行が推奨されていますが、私の用途ではオーバースペックでコストが見合わず※1、最終的にAmazon S3+CloudFrontへの移行を選びました。その過程で、Pythonスクリプトを用いて効率よく移行を行う方法を開発しました。

※1 Azure Front Doorは高機能で優れた選択肢ですが、基本料金が高額で、小規模なWebサイトでは費用対効果が低い場合があると思います。

課題と解決策

移行作業では、AWS DataSyncも試しましたが、自由度が低く、私の求める柔軟性を満たせませんでした。そのため、自作のPythonスクリプトを使い、以下の機能を実現しました。

  • Azure Blobストレージから(ローカル環境へ)のデータ取得
  • Amazon S3へのアップロード
  • 実行時のログやエラーを管理

このあと、CloudFrontでHTTPS対応のホスティングを設定する作業は説明資料に従って進めてください。

スクリプトは以下のGitHubリポジトリで公開しています。興味がある方はぜひご覧ください。

本スクリプトおよび資料は、現状のまま(AS IS)で提供されており、いかなる保証も行いません。本スクリプトの使用により発生したいかなる損害や問題についても、作成者は一切の責任を負いかねます。ご利用は自己責任でお願いいたします。

説明資料

詳細な手順はREADME.mdに記載しています。以下にもその内容を転載しておきます。

https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png

Azure Blob to S3 Migration

このプロジェクトは、Azure Blobストレージからファイルをダウンロードし、Amazon S3にアップロードするためのPythonスクリプトを提供します。

また、アップロードした後に、Amazon S3をスタティック(静的)なWebサイトホスティングサービスとして構成し、Amazon CloudFrontによりCDNで配信されるようにし、AWS Certificate Manager(ACM)により生成し自動更新されるHTTPS用のSSL証明書を設定するまでの作業手順も、このREADME.mdファイルに掲載しています。

ただし、スクリプトはWindows環境で実行しているため、それ以外の環境での動作は保証できません。細かい調整が必要な場合は、スクリプトを修正することで対応してください。

※本スクリプトの実行は自己責任で行ってください。いかなる責任も負いません。また、本スクリプトにPR(プルリクエスト)やIssue(問題報告)を送られても、一切対応しませんので、あしからずご了承ください。

構成

  • requirements.txt: 必要なPythonパッケージのリスト。
  • config.ini: 認証情報を含む設定ファイル。
  • AzureBlobDownload.py: Azure Blobストレージからファイルをダウンロードします。
  • AwsS3Upload.py: ダウンロードされたファイルをAmazon S3にアップロードします。
  • BlobS3Compare.py: 念のため、Azure BlobストレージとAmazon S3の内容を比較します。開発者が3サイトで実施して失敗はなかったため不要かもしれません。

ログファイル

  • <Blob名>_download_log.txt: Azure Blobストレージからのダウンロードに関するログ。
  • <S3名>_upload_log.txt: Amazon S3へのアップロードに関するログ。
  • <S3名>_compare_log.txt: Azure BlobストレージとAmazon S3の内容比較に関するログ。

リトライ機能

※本プロジェクト開発者が試した限りでは、失敗が発生したことがないため、リトライ機能は実装済みですが、正常に稼働するかは検証されていません。

  • ダウンロードやアップロードに失敗したファイルは、リトライ用のファイルに記録されます。
  • 次回実行時にリトライ用のファイルを読み込み、前回失敗した処理を再試行します。成功した処理は再試行しません。
  • 全てのファイルが成功した場合、リトライ用のファイルは削除されます。

前提条件

Azure BlobストレージをWebサーバとして活用してスタティックなWebページや画像を配信していることを前提としています。また、Azure CDNなどでCDNとSSLの自動更新を対応している場合もカバーしています。

既存のAzure Blobストレージが存在するあることを前提としています。また、同名のAmazon S3バケットを以下の手順で作成しておいてください。

S3バケットを作る手順

作成時に以下の内容を指定することを前提とします。

  1. AWS リージョンは「アジアパシフィック (東京) ap-northeast-1」とします。
  2. AWSコンソールでS3の[汎用バケット]を開き、[バケットを作成]をクリックします。
  3. [バケットタイプ]は「汎用」を選択します。
  4. [バケット名]はAzure Blobストレージアカウントと同じ名前にします。例:remasahiko
  5. [ACL無効]を選択してください。
  6. [パブリックアクセスをすべてブロック]のチェックを外してください。
  7. [バケットのバージョニング]は「有効にする」にしてください。
  8. [タグ - オプション]でキーは「Name」、値は「<任意のプロジェクト名(例:masahiko.info)>」でタグを追加してください。
  9. 他はデフォルトのまま[バケットを作成]をクリックしてください。
  10. これでS3バケットの作成は完了です。

必要なPythonパッケージ

以下のコマンドを使用して、必要なパッケージをインストールしてください。

pip install -r requirements.txt

認証情報の設定

Azure Blobストレージアカウントの接続文字列の取得

  1. Azureで対象のストレージアカウントを開き、左のメニューから[セキュリティとネットワーク]-[アクセスキー]を選択します。
  2. [接続文字列]をコピーします。

AWSのアクセスキーの取得

AWSのアクセスキーはユーザーごとに取得します。セキュリティの問題もあるので、全ての作業が終わったら無効化もしくは削除するのがお勧めです。

  1. AWS Management Consoleにログインし、IAMサービスに移動します。
  2. 左側のメニューから[ユーザー]を選択します。
  3. 該当のユーザー名をクリックします。
  4. 上部の[セキュリティ認証情報]タブを開きます。
  5. [アクセスキーを作成]をクリックします。
  6. [ユースケース]は「ローカルコード」を選択します。
  7. [説明タグ値]は空のままで[アクセスキーを作成]をクリックします。
  8. これにより、アクセスキーIDとシークレットキーが発行されるので、確実にどこかに記述してください。

config.iniの編集

ご自身の環境に合わせて修正してください。

  • ConnectionString: Azure Blob Storageの接続文字列を設定します。
  • BlobStorageName: Blobストレージ名を指定します。
  • S3BucketName: 比較対象のS3バケット名を設定します。
  • AccessKeyId: AWSアクセスキーIDを設定します。
  • SecretAccessKey: AWSシークレットアクセスキーを設定します。
  • Region: AWSリージョンを設定します。

使用方法

AzureBlobDownload.pyの使用方法

(1) AzureBlobDownload.pyを実行して、Azure Blobストレージからファイルをダウンロードします。

python AzureBlobDownload.py

注意点として、パブリックアクセスが 'container' 以外のコンテナ(プライベートやBLOBなど)はスキップする仕様なので注意してください。必要があればプログラムを書き換えてください。

(2) ダウンロードされたファイルは、指定されたローカルディレクトリに保存されます。

AwsS3Upload.pyの使用方法

(1) AwsS3Upload.pyを実行して、ダウンロードされたファイルをAmazon S3にアップロードします。

python AwsS3Upload.py

(2) アップロードの成功または失敗はログファイルに記録されます。

BlobS3Compare.pyの使用方法

(1) BlobS3Compare.pyを実行して、Azure BlobストレージとAmazon S3の内容を比較します。

python BlobS3Compare.py

(2) 比較の結果はログファイルに記録されます。

全て成功すれば作業は完了です。

S3バケットをスタティックなWebサイトホスティングサービスにするまでの手順

注意事項

  • パブリックアクセスを有効化する際はセキュリティに注意してください。不要なデータが公開されないように。
  • 公開したくないファイルはそもそもアップロードしない方がよいでしょう。このスクリプトではもともとAzure Blobストレージでパブリックに公開されていたBlobのみを移行する仕様になっていますので、基本的には新たに不要なデータが公開されることはないはずです。

手順 1: 静的Webサイトホスティングを有効化

  1. AWSコンソールで対象のS3バケットを選択します。
  2. 上部メニューの[プロパティ]をクリックしてください。
  3. [静的Webサイトホスティング]セクションの[編集]をクリック。
  4. 「静的Webサイトホスティング」の「有効にする」を選択します。
  5. [ホスティングタイプ]jは、「静的ウェブサイトをホストする」を選択します。
  6. [インデックスドキュメント](例: index.htmldefault.html)を入力。
    • 必要なら[エラードキュメント](例: error.html)も入力。このファイルは基本的にバケットのルート(トップレベル)に配置してください。
  7. [変更の保存]をクリックします。

サンプルのerror.htmlファイルをこのプロジェクトに含めていますので、これをS3バケットのトップレベルにアップロードしてみてください。

手順 2: ブロックパブリックアクセスをオフにする

この作業は、作成時にオフにしていれば不要です。

  1. 上部メニューの[アクセス許可]をクリック。
  2. [ブロックパブリックアクセス (バケット設定)]セクションの[編集]をクリック。
  3. すべてのチェックボックスをオフにします。
  4. 保存します。
  5. 注意: この設定変更により、バケットがパブリックにアクセス可能になるリスクがあります。次のポリシー設定を適切に行いましょう。

手順 3: バケットポリシーを設定

S3バケットをパブリックにアクセス可能にするため、バケットポリシーを記載します。

以下は、特定のS3バケット(例: example-bucket)内のすべてのオブジェクトをパブリックにするポリシーです。arn:aws:s3:::example-bucketの部分は「バケット ARN」と呼ばれますが、編集画面上でコピーできます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
  1. 引き続き[アクセス許可]にある[バケットポリシー]セクションの[編集]をクリック。
  2. 上記のJSONコードを貼り付けます(example-bucketを実際のバケット名に変更)。
  3. 保存します。

手順 4: オブジェクト所有者を確認

S3バケットの[アクセス許可]で[オブジェクト所有者]が「バケット所有者の強制」となっている場合、ACL(アクセスコントロールリスト)は無効になっています。つまり、このバケット内のすべてのオブジェクトは、このアカウントによって所有されます。このバケットとそのオブジェクトへのアクセスは、ポリシーのみを使用して指定されます。

このプロジェクトでは、ACLが無効であることを前提としています。ACLが有効な場合、バケットポリシーを設定しても、オブジェクト(ファイル)がパブリックでない場合があります。

手順 5: WebサイトのURLにアクセス

スタティックWebサイトのURLは、以下の形式になります。

http://{バケット名}.s3-website-{リージョン}.amazonaws.com
http://remasahiko.s3-website-ap-northeast-1.amazonaws.com
  1. 対象のS3バケットの上部メニューの[プロパティ]をクリックしてください。
  2. 一番下の[静的ウェブサイトホスティング]にある「バケットウェブサイトエンドポイント」のURLを開いてみてください。個別のオブジェクトにアクセスできるかは後で確認します。
  3. 上部メニューの[オブジェクト]から任意のオブジェクトを開いてください。
  4. 上部メニューの[プロパティ]を開き、[オブジェクトの概要]の[オブジェクト URL]を開いて、実際にWebアクセスできるかを確認してください。
  5. これによりHTMLページや画像などが正常に表示されれば、S3のスタティックなWebサイトの公開は完了です。

S3バケットのサイトがCDN(カスタムドメインSSL証明書あり)で配信されるまでの手順

Amazon CloudFrontの手順の中で、AWS Certificate Manager(ACM)を使ってカスタムドメイン用のSSL証明書を取得するようになっています。証明書の発行時にDNS検証を選択することによって、期限切れの60日前に自動更新されます。

Amazon CloudFrontの設定手順

  1. CloudFrontディストリビューションの作成

    1. AWS Management Consoleにログインし、CloudFrontサービスに移動します。
    2. [CloudFront ディストリビューションを作成]をクリックします。
    3. [Origin domain]で、S3バケットのエンドポイントを選択し、それにより表示される[Web サイトのエンドポイントを使用]をクリックします。
      • 例: - <バケット名>.s3-website-<リージョン>.amazonaws.com
    4. [名前]は自動的に入力されます。
    5. [デフォルトのキャッシュビヘイビア]セクションで[ビューワープロトコルポリシー]を「Redirect HTTP to HTTPS」に設定します。
    6. [ウェブアプリケーションファイアウォール (WAF) ]セクションで「セキュリティ保護を有効にしないでください」を選択します。追加費用を発生させないためです。必要になったらONにすればよいと思います。
    7. [設定]セクションの[料金クラス]で、日本メインなら「北米、欧州、アジア、中東、アフリカを使用」を選択します。性能と価格のバランスがよいためです。世界中からアクセスされるなら「すべてのエッジロケーションを使用する (最高のパフォーマンス)」がよいでしょう。
    8. その下の[代替ドメイン名 (CNAME) - オプション]で、[項目を追加]をクリックして、カスタムドメイン名(例:re.masahiko.info)を入力します。
    9. その下の[Custom SSL certificate - optional]で、[証明書をリクエスト]リンクをクリックします。
      • [パブリック証明書をリクエスト]を選択して[次へ]をクリックします。
      • [完全修飾ドメイン名]にカスタムドメイン名(例:re.masahiko.info)を入力します。
      • [検証方法]は「DNS 検証 - 推奨」に必ずしてください。
      • 他はデフォルトの推奨設定のままにします。
      • リソースグループで管理しやすいように[タグ]も付けるのがお勧めです。キーは「Name」として、値は「masahiko.info」など独自のグループ名を指定します。
      • [リクエスト]をクリックします。
      • [ステータス]が「保留中の検証」となるので、検証用にDNSのCNAMEの追加が必要です。お使いのDNSの設定箇所で、[ドメイン]内の表で取得できる「CNAME名」からサブドメインまでの部分(例:_abcdef123456gh7i8j9klm01n2opq345.<subdomain>)を名前として、「CNAME値」(ドメイン名で場合によっては最後の.を除いて内容、例:_a0123bcdefghigklmnopqrst45fvwxyz.zfyfvmchrl.acm-validations.aws.)を値(正規名)として指定してください。
      • 30分もしないうちに発行済みになります。[ステータス]に「発行済み」と表示されるまで待ちます。ブラウザーでリロードすると表示が変わる場合があります。
    10. CloudFrontのディストリビューション作成画面に戻ります。
    11. [Custom SSL certificate - optional]の右端の更新ボタンをクリックした後で、先ほど作成したSSLを[Custom SSL certificate - optional]で選択します。
    12. [Default root object - optional]にルート(/)でアクセスされたときに自動表示するファイル名(例: index.htmldefault.html)を入力。
    13. [ログ配信]は必要があればオンにしてください。ただし追加費用がかかるため、私の場合はオフにしています。
    14. [ディストリビューションを作成]をクリックします。
  2. CloudFrontディストリビューションのデプロイ

    • ディストリビューションのステータスが「有効」になるまで待ちます。わたしの場合はすぐでしたが、数分かかることがあるようです。
    • ディストリビューションのステータスは、CloudFrontのトップページでも確認できます。
  3. CloudFrontディストリビューションの確認

    • CloudFrontディストリビューションの[ディストリビューションドメイン名]を使用して、S3に配置したオブジェクトのパスのWebページや画像にアクセスして、無事に表示されるのを確認します(表示されるようになるまでに数分かかります)。例: d123456abcdef8.cloudfront.net
    • [ディストリビューションドメイン名]はCDN設定で使うので、保存しておいてください。

カスタムドメインのDNS設定と確認

最後にカスタムドメインでアクセスされるように設定すれば完了です。

カスタムドメインのCNAMEの内容(ドメイン名)に[ディストリビューションドメイン名]を指定してください。[ディストリビューションドメイン名]はCloudFrontで確認できます。

念のため、依然のCNAME内容は一時的に何かに書き写してバックアップしておきましょう。

反映まで1時間ほどかかります。長い場合は72時間程度も時間がかかることがあります。反映されたかはSSL証明書をブラウザから確認すればよいでしょう。もしくは以下のコマンドで確認できます。

nslookup <カスタムドメイン名>

ここまで出来たらAzure BlobストレージとAzure CDNの役目も終了なので、削除しても構いません。が、トラブル回避のため、72時間ほど様子を見てからの方がよいかもしれません。

全ての作業が終わったら、AWSのアクセスキーは無効化するか、削除しておきましょう。

ライセンス

このプロジェクトはApache License 2.0の下で公開されています。詳しくはLICENSEファイルをご確認ください。