Скрипт на Python для создания оффлайн копии блога

2 ноября 2024

Народная мудрость гласит, что интернет все помнит. Практика, однако, этого не подтверждает. Как человеку, который 10+ лет исправляет битые ссылки в данном блоге, можете мне поверить. Названные обстоятельства заставили задуматься о создании надежной копии «Записок программиста».

Был написал следующий скрипт на Python:

#!/usr/bin/env python3

# 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, а на локальную копию репозитория. Допускается ссылаться на конкретные файлы и каталоги внутри репозитория, но не на коммиты.

Копия сайта сохраняется на надежном носителе:

Оффлайн копия блога EAX.ME на оптическом диске

Примечательный факт: с диска блог можно читать даже на 25-и летнем ноутбуке в браузере Internet Explorer 8.0 или Firefox 1.0. Сайт верстался в конце 2000-х, и потому прекрасно совместим как с новыми, так и со старыми браузерами.

Теперь, даже если дата-центры моего хостера и GitHub’а одновременно накроет цунами, у меня останется копия блога на CD. Резервные копии скриптов и базы данных у меня тоже есть. Однако «Записки программиста» работают на старых технологиях. Мне кажется, что перенести блог к новому хостеру будет непросто. В случае чего мне проще «заморозить» текущую версию блога и начать блог 2.0 на более новых технологиях.

Метки: , , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.