Скрипт на Python для создания оффлайн копии блога
2 ноября 2024
Народная мудрость гласит, что интернет все помнит. Практика, однако, этого не подтверждает. Как человеку, который 10+ лет исправляет битые ссылки в данном блоге, можете мне поверить. Названные обстоятельства заставили задуматься о создании надежной копии «Записок программиста».
Был написал следующий скрипт на Python:
# https://eax.me/ full offline copy
# Aleksander Alekseev, 2024
from datetime import datetime as dt
import subprocess
import glob
import sys
import os
import re
dirname = dt.today().strftime('%Y-%m-%d')
os.makedirs(dirname+"/files/github", exist_ok=True)
code = subprocess.call("wget -r -l 0 -k -nH https://eax.me/ -P " +
dirname +" 2>&1 | tee wget.log", shell=True)
if code != 0:
print("Wget returned {}, check wget.log for 404s," +
" 301s, etc".format(code))
sys.exit(1)
os.remove("wget.log")
for page_path in glob.glob(dirname + '/**/index.html', recursive=True):
page_data = ""
with open(page_path) as page_f:
page_data = page_f.read()
re_str = """<a[ ]+href=['"]https?://github.com/afiskon/([^'"/]+)"""
for m in re.finditer(re_str, page_data):
repo_name = m.group(1)
print("Found repo: {} in {}".format(repo_name, page_path))
repo_backup_dir = dirname+"/files/github/"+repo_name;
if not os.path.isdir(repo_backup_dir):
print(" New one, cloning...")
code = subprocess.call(
"git clone --depth 1 https://github.com/afiskon/" +
repo_name + ".git " + repo_backup_dir, shell=True)
if code != 0:
print("Failed to clone {}, git returned {}".format(
repo_name, code))
sys.exit(1)
page_data = re.sub(
"""(<a[ ]+href=["'])https?://github.com/afiskon/([^'"/]+)""" +
"""(/tree/master|/tree/main|/blob/master|/blob/main)?""" +
"""([^'"]*["'])""",
r"\1../files/github/\2\4",
page_data)
# remove LiveInternet JavaScript code
page_data = re.sub(
"""(?s)<script type="text/javascript">.*?</script>""",
"", page_data)
print("Updating {}".format(page_path))
with open(page_path, 'w') as page_f:
page_f.write(page_data)
subprocess.check_call(
"rm -rf "+dirname+"/files/github/*/.git",
shell=True)
subprocess.check_call(
"tar -cvzf "+dirname+".tgz "+dirname,
shell=True)
subprocess.check_call(
"rm -rf "+dirname,
shell=True)
print("DONE!")
Примечание: Обратите внимание на пост Памятка по регулярным выражениям, если вдруг вы его пропустили.
Большую часть работы здесь выполняет команда wget -r -k
. Она рекурсивно скачивает сайт, а затем исправляет абсолютные адреса на относительные. Это работает с большинством статических и CGI сайтов. Главное — следить, чтобы в robots.txt через директиву Disallow:
не был запрещен доступ к каким-нибудь важным файлам.
Существенная часть контента «Записок программиста» приходится на исходники, которые я публикую на GitHub. Их тоже хотелось бы сохранять. Основная часть скрипта этим и занимается.
Сохраненные посты изучается на предмет наличия ссылок, которые начинаются с github.com/afiskon/
. Когда находится ссылка на репозиторий, он скачивается командой git clone --depth 1
. История коммитов при этом теряется, но в моем коде она не несет особой ценности. Копия поста исправляется так, чтобы ссылка вела не на GitHub, а на локальную копию репозитория. Допускается ссылаться на конкретные файлы и каталоги внутри репозитория, но не на коммиты.
Копия сайта сохраняется на надежном носителе:
Примечательный факт: с диска блог можно читать даже на 25-и летнем ноутбуке в браузере Internet Explorer 8.0 или Firefox 1.0. Сайт верстался в конце 2000-х, и потому прекрасно совместим как с новыми, так и со старыми браузерами.
Теперь, даже если дата-центры моего хостера и GitHub’а одновременно накроет цунами, у меня останется копия блога на CD. Резервные копии скриптов и базы данных у меня тоже есть. Однако «Записки программиста» работают на старых технологиях. Мне кажется, что перенести блог к новому хостеру будет непросто. В случае чего мне проще «заморозить» текущую версию блога и начать блог 2.0 на более новых технологиях.
Метки: Python, Блогинг, Сайтостроение.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.