メモ:ウェブサイトをローカル保存する方法
良いサイトを見つけたのだが、なにせページ数が膨大で、手動でコピペする案件ではなかったため、自動でエイヤとできないものかと模索した記録を残しておく。
検索では、どうやらwgetなるものを使えばいいということだけは分かったのだが、あいにくLinuxではなくWindowsユーザーなので、環境を整えるところから始まった。
wget導入
まずこのサイトからwgetを落とす。
全部使う訳ではなさそうだったが、自分にはよくわからないのでとりあえずComplete packageにした。任意のフォルダに保存。
hogehoge/wget/bin のパスをメモっておく。
タスクバーの窓アイコンを右クリックし、Power Shellを管理者権限で起動する。
[System.Environment]::SetEnvironmentVariable(
"Path",
$env:Path + ";C:hogehoge/wget/bin",
"Machine"
)
上記のコマンドを実行することで「パスを通す」ことができる。
しかし、この状態だとWindowsに元からあるエイリアスと競合して使いたい方のwgetが仕えない。
そこで、プロファイルにエイリアス削除を追記する。
notepad $PROFILE
ファイルが存在しないと言われたら
New-Item -ItemType File -Path $PROFILE -Force
notepad $PROFILE
開いたメモ帳に以下を追加して保存
Remove-Item Alias:wget -ErrorAction SilentlyContinue
PowerShellを閉じて開き直して確認
Get-Command wget
Sourceがhogehoge/wget/bin/wget.exeになっていればOK。
URLリストを作る
wget単体でもページネーションを遡ることは可能らしいが、bloggerで作られたサイトでは上手くいかなかった。
そこで先にPythonでURLリストを作成する。
import requests
from bs4 import BeautifulSoup
import time
base_url = "https://fugafuga.com/"
urls = set()
next_url = base_url
while next_url:
print(f"取得中: {next_url}")
res = requests.get(next_url)
soup = BeautifulSoup(res.text, "html.parser")
# 記事URLを収集
for a in soup.select("h3.post-title a, h2.post-title a"):
urls.add(a["href"])
# 次のページリンクを探す
older = soup.select_one("a.blog-pager-older-link")
next_url = older["href"] if older else None
time.sleep(1)
# URLリストをファイルに保存
with open("C:hogehoge/urls.txt", "w") as f:
for url in sorted(urls):
f.write(url + "\n")
print(f"\n合計 {len(urls)} 記事のURLを収集した")
すると.txtにURLの一覧が出来上がる。
wgetを実行
ここから先は失敗例なので、次の章まで飛ばしてもよし。
さていよいよwgetの実行である。
cd "urls.txtのあるフォルダのパスを指定"
Remove-Item Alias:wget -ErrorAction SilentlyContinue
wget --input-file="urls.txt" --convert-links --no-check-certificate `
--wait=1 --random-wait `
-R "svg,ico,css,js" `
—no-check-certificateは大概のレンタルブログサービスだとナントカとナントカが一致しないために上手く実行できないので、強行突破するためにこの呪文を追加する。ウィルスを掴まされても自己責任だぞ。
しかし同じ名前のファイルが複数発生してしまい、blog-post.html.12のような数字の謎拡張子ファイルが大量発生してしまった。これでも中身が見れないことはないが、次のステップでmdファイルに一括変換するつもりだったので、これでは困る。
Pythonでwget実行
Pythonのスクリプト経由でwgetを実行することに。
import requests
from bs4 import BeautifulSoup
from pathlib import Path
import time
import re
input_file = Path(r"C:hogehoge\urls.txt")
output_dir = Path(r"C:hogehoge\html")
output_dir.mkdir(parents=True, exist_ok=True)
urls = input_file.read_text(encoding="utf-8").splitlines()
def sanitize(name):
return re.sub(r'[\\/:*?"<>|]', "", name).strip()[:80]
for url in urls:
try:
# URLから年月を取得 例: /2019/10/blog-post.html
parts = url.rstrip("/").split("/")
year_month = "_".join(parts[-3:-1]) # 例: 2019_10
res = requests.get(url)
res.encoding = "utf-8"
soup = BeautifulSoup(res.text, "html.parser")
# タイトル取得
title_tag = soup.select_one("h3.post-title, h2.post-title")
title = sanitize(title_tag.get_text()) if title_tag else parts[-1].replace(".html", "")
filename = f"{year_month}_{title}.html"
out = output_dir / filename
out.write_text(res.text, encoding="utf-8")
print(f"保存: {filename}")
time.sleep(1)
except Exception as e:
print(f"エラー: {url} → {e}")
これで、日付+記事名のhtmlファイルとして保存完了。
あとは煮るなり焼くなり、よしなに。
まだリアクションがありません