特定ユーザーの Yahoo! ブログ を wget でまるごと保存する


参考「[Yahoo!ブログ サービス終了のお知らせ](https://promo-blog.yahoo.co.jp/close/index.html)」(wget は関係ないです)

Yahoo! ブログ がサービス終了するという事で、一応自身のブログについては移行ツールが用意されるらしいですが、一部データは移行できなかったり (コメント、トラックバック、ブログデザインなど) 、すでに更新が停止している他のひとのブログは保存できなかったりするので、wget でまるごと保存してみることにしました。

何も考えずに wget してしまうと、ドメインが異なる css や画像を保存できなかったり、リンクがあるさらに別のひとのブログまで保存しようとしたりしてしまうので、いろいろと注意が必要です。

# 1. コマンド

今回は Windows Subsystem for Linux を使って保存することを想定しています。
(Yahoo! のサーバーに負荷をかけると思うので、適度に実行してください…。)

## 1.1. 通常

```bash:コマンド
wget --mirror \
	--page-requisites \
	--span-hosts \
	--quiet --show-progress \
	--no-parent \
	--convert-links \
	--adjust-extension \
	--execute robots=off \
	--domains=blogs.yahoo.co.jp,yimg.jp,storage-yahoo.jp \
	--restrict-file-names=windows \
	https://blogs.yahoo.co.jp/(ユーザーIDまたはニックネーム)/
```

## 1.2. ログインした状態で取得

```bash:コマンド追加
	--header='Cookie: (クッキー)' \
	--reject='write.html*' \
```

ログインした状態で保存したい場合は `--header='Cookie: (クッキー)'` を使います。ブラウザの開発者ツールでリクエストヘッダーにある Cookie を調べ、まるごと張り付けたらできました。

ログイン済みかつ自身のブログを保存すると、編集用ページの `write.html` が大量に保存されてしまうので、`--reject='write.html*'` を付け加えた方が良さそうです。

## 1.3. サーバーの負荷を軽減

必要に応じて書き換えてください。

```bash:コマンド追加
	--wait=3 --random-wait \
```

## 1.4. (参考) `--no-parent` の代わりに `--reject-regex` を使う

```bash:コマンド削除
	--no-parent \
```

```bash:コマンド追加
	--reject-regex='https://blogs.yahoo.co.jp/(?!ユーザーIDまたはニックネーム(/.*)?$).*' --regex-type=pcre \
```

※ディレクトリが一部誤って保存されます

# 2. 説明

主に以下の記事を参考にしました。

参考「[wgetでサイト全体をまるごとダウンロードする(認証後ページも) - Qiita](https://qiita.com/suin/items/7241135f1684636652ac)」

詳しいことは参考ページで確認ください。
ここでは参考ページになかったことを書きます。

- `--domains`: 別ドメインからも保存するために `--span-hosts` を指定するのはいいのですが、そのままだと Yahoo! のヘルプページや別のサービスのページまで保存してしまうので、ドメインを制限します。
    - `blogs.yahoo.co.jp`: ブログ本体
    - `yimg.jp`: ブログデザインの css, js, 画像
    - `storage-yahoo.jp`: ユーザーがアップロードした画像
- `--restrict-file-names=windows`: Windows Subsystem for Linux 環境だとファイル名の `?` (クエスチョンマーク、クエッションマーク、インテロゲーションマーク、はてなマーク、疑問符) などが文字化けして css, js, 画像などが読み込めなくなるので、`windows` に指定します。
- ***URLの末尾に `/` が必要***: 上記参考ページには「`https://example.com/foo`のようにすると、`/foo`以下がダウンロード対象。」とありますが、***これは間違いです***。GNU Wget のドキュメントにも書かれていますが、末尾に `/` がないとディレクトリではなくファイル名として認識され、思い通りに動きません。
- `--no-host-directories`: 単に好みの問題でなくしました。

参考「[--no-parent - GNU Wget 1.20 Manual](https://www.gnu.org/software/wget/manual/wget.html#index-no-parent)」

> ***Note*** that, for HTTP (and HTTPS), the trailing slash is very important to ‘--no-parent’. HTTP has no concept of a “directory”—Wget relies on you to indicate what’s a directory and what isn’t. In ‘http://foo/bar/’, Wget will consider ‘bar’ to be a directory, while in ‘http://foo/bar’ (no trailing slash), ‘bar’ will be considered a filename (so ‘--no-parent’ would be meaningless, as its parent is ‘/’).

> (意訳)
> ***注意***、HTTP (や HTTPS) において、末尾のスラッシュは ‘--no-parent’ するときにとても重要です。HTTP には「ディレクトリ」の概念がないので、あなたがディレクトリであるかないかを Wget に示す必要があります。‘http://foo/bar/’ であれば Wget は 'bar' がディレクトリとみなし、‘http://foo/bar’ (末尾スラッシュなし) であれば 'bar' はファイル名としてみなされるでしょう (その場合 ‘--no-parent’ は意味がなくなり、親ディレクトリは ‘/’ となるでしょう) 。

# 3. 問題点

## 3.1. トップページへのリンクがローカル用に置換されない

上記の「[1.1. 通常](#11-通常)」の方法だと `https://blogs.yahoo.co.jp/(ユーザーIDまたはニックネーム)` (末尾スラッシュなし) が親ディレクトリにあるファイルであるとみなされ、Yahoo! ブログのトップページへのリンクがローカル用に置換されません。
`--include-directories=` を使う方法も試してみましたが、他ドメインにも影響しているのか、自分が試した範囲だと上手く保存できませんでした…。

「[1.4. (参考) --no-parent の代わりに --reject-regex を使う](#14-%E5%8F%82%E8%80%83---no-parent-%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%AB---reject-regex-%E3%82%92%E4%BD%BF%E3%81%86)」の方法ではトップページが別ページとして保存され、リンクはつながるようになります。
(ディレクトリが一部誤って保存されます。)

## 3.2. 記事が存在しない「カテゴリ」ページなどが保存されない

記事が存在しない「カテゴリ」ページでは「記事がありません」とブラウザ上では表示されるのですが、レスポンスヘッダのステータスコードを見ると 404 扱いになっていて、wget で保存することができません…。

## 3.3. (要検証) 他にローカル用に置換されないリンクがある

ちゃんと原因を調べていないのですが、「アーカイブ」用のリンクなどが置換されないようです…。