Недавно я глубоко погрузился в тему архивирования веб-сайтов. Меня попросили друзья, которые боялись потерять контроль над своими работами в интернете из-за плохого системного администрирования или враждебного удаления. Такие угрозы делают архивирование веб-сайтов важным инструментом любого сисадмина. Как оказалось, некоторые сайты гораздо сложнее архивировать, чем другие. Эта статья демонстрирует процесс архивирования традиционных веб-сайтов и показывает, как он не срабатывает на модных одностраничных приложениях, которые раздувают современный веб.
Давно прошли дни, когда веб-сайты писались вручную на HTML. Теперь они динамичные и строятся «на лету» с использованием новейших JavaScript, PHP или Python-фреймворков. Как результат, сайты стали более хрупкими: сбой базы данных, ложное обновление или уязвимости могут привести к потере данных. В моей предыдущей жизни в качестве веб-разработчика мне пришлось смириться с мыслью: клиенты ожидают, что веб-сайты будут работать вечно. Это ожидание плохо сочетается с принципом веб-разработки «двигаться быстро и ломать вещи». Работа с системой управления контентом Drupal оказалась особенно сложной в этом отношении, поскольку крупные обновления намеренно нарушают совместимость со сторонними модулями, что подразумевает дорогостоящий процесс обновления, который клиенты редко могут себе позволить. Решение состояло в том, чтобы архивировать эти сайты: взять живой, динамический веб-сайт — и превратить его в простые HTML-файлы, которые любой веб-сервер может выдавать вечно. Этот процесс полезен для ваших собственных динамических сайтов, а также для сторонних сайтов, которые находятся вне вашего контроля, и которые вы хотите защитить.
С простыми или статичными сайтами отлично справляется почтенная программа Wget. Хотя для зеркалирования всего сайта понадобится настоящее заклинание:
Эта команда загружает содержимое веб-страницы, а также выполняет обход всех ссылок в указанных доменах. Перед запуском этого действия на любимом сайте рассмотрите возможные последствия краулинга. Приведённая выше команда намеренно игнорирует правила robots.txt, как сейчас принято у архивистов, и скачивает сайт на максимальной скорости. У большинства краулеров есть опции для паузы между обращениями и ограничения полосы пропускания, чтобы не создавать чрезмерную нагрузку на целевой сайт.
Эта команда также получает «реквизиты страницы», то есть таблицы стилей (CSS), изображения и скрипты. Загруженное содержимое страницы изменяется таким образом, что ссылки указывают уже на локальную копию. Результирующий набор файлов может быть размещён на любом веб-сервере, представляя собой статическую копию исходного веб-сайта.
Но это когда всё идёт хорошо. Любой, кто когда-либо работал с компьютером, знает, что вещи редко идут по плану: есть множество интересных способов сорвать процедуру. Например, некоторое время назад на сайтах было модно ставить блоки с календарём. CMS будет генерировать их «на лету» и отправит краулеры в бесконечный цикл, пытаясь получить всё новые и новые страницы. Хитрые архивариусы могут использовать регулярные выражениям (например, в Wget есть опция
К сожалению, некоторые веб-сайты представляют собой гораздо больше, чем просто HTML. Например, на одностраничных сайтах веб-браузер сам создаёт контент, выполняя небольшую программу JavaScript. Простой пользовательский агент, такой как Wget, будет безуспешно пытаться восстановить значимую статическую копию этих сайтов, поскольку он вообще не поддерживает JavaScript. Теоретически, сайтам следует поддерживать прогрессивное улучшение, чтобы контент и функциональность были доступны без JavaScript, но эти директивы редко соблюдаются, как подтвердит любой, кто использует плагины вроде NoScript или uMatrix.
Традиционные методы архивирования иногда терпят неудачу самым тупым образом. При попытке сделать бэкап местной газеты я обнаружил, что WordPress добавляет строки запросов (например,
Поскольку браузер постепенно становится виртуальной машиной для запуска произвольного кода, то методам архивирования, основанным на чистом анализе HTML, следует адаптироваться. Решением этих проблем является запись (и воспроизведение) HTTP-заголовков, доставляемых сервером во время краулинга, и действительно профессиональные архивисты используют именно такой подход.
В Интернет-архиве Брюстер Кале и Майк Бёрнер в 1996 году разработали формат ARC (ARChive): способ объединить миллионы небольших файлов, созданных в процессе архивирования. В конечном итоге формат стандартизировали как спецификацию WARC (Web ARChive), выпущенную в качестве стандарта ISO в 2009 году и пересмотренную в 2017 году. Усилия по стандартизации возглавил Международный консорциум по сохранению Интернета (IIPC). Согласно Википедии, это «международная организация библиотек и других организаций, созданных для координации усилий по сохранению интернет-контента для будущего», в неё входят такие члены, как Библиотека Конгресса США и Интернет-архив. Последний использует формат WARC в своём Java-краулере Heritrix.
Файл WARC объединяет в одном сжатом архиве несколько ресурсов, таких как заголовки HTTP, содержимое файла и другие метаданные. Удобно, что этот формат поддерживается и краулером Wget с параметром
Кстати, этот инструмент создали разработчики сервиса Webrecorder, который с помощью браузера сохраняет динамическое содержимое страницы.
К сожалению, pywb не умеет загружать WARC-файлы, сгенерированные Wget, потому что он подчиняется некорректным требованиям спецификации WARC 1.0, которые были исправлены в версии 1.1. Пока Wget или pywb не устранят эти проблемы, файлы WARC, созданные Wget, недостаточно надёжны, поэтому лично я начал искать другие альтернативы. Моё внимание привлёк краулер под простым названием crawl. Вот как он запускается:
Программа поддерживает некоторые параметры командной строки, но большинство значений по умолчанию вполне работоспособны: она скачает ресурсы вроде CSS и картинок с других доменов (если не указан флаг
Есть немало ресурсов по использованию файлов WARC. В частности, есть замена Wget под названием Wpull, специально разработанная для архивирования веб-сайтов. Она имеет экспериментальную поддержку PhantomJS и интеграцию с youtube-dl, что позволит загружать более сложные JavaScript-сайты и скачивать потоковое мультимедиа, соответственно. Программа является основой инструмента архивирования ArchiveBot, разработку которого ведёт «свободный коллектив озорников-архивистов, программистов, писателей и болтунов» из ArchiveTeam в попытке «сохранить историю, прежде чем она исчезнет навсегда». Похоже, что интеграция PhantomJS не так хороша, как хотелось бы, поэтому ArchiveTeam использует ещё кучу других инструментов для зеркалирования более сложных сайтов. Например, snscrape сканирует профили социальных сетей и генерирует списки страниц для отправки в ArchiveBot. Другой инструмент — crocoite, который запускает Chrome в headless-режиме для архивирования сайтов с большим количеством JavaScript.
Эта статья была бы неполной без упоминания «ксерокса сайтов» HTTrack. Аналогично Wget, программа HTTrack создаёт локальные копии сайтов, но, к сожалению, не поддерживает сохранение в WARC. Интерактивные функции могут быть более интересны начинающим пользователям, незнакомым с командной строкой.
В том же духе, во время своих исследований я нашёл альтернативу Wget под названием Wget2 с поддержкой многопоточной работы, которая ускоряет работу программы. Однако здесь отсутствуют некоторые функции Wget, в том числе шаблоны, сохранение в WARC и поддержка FTP, зато добавлены поддержка RSS, кэширование DNS и улучшенная поддержка TLS.
Наконец, моей личной мечтой для таких инструментов было бы интегрировать их с моей существующей системой закладок. В настоящее время я храню интересные ссылки в Wallabag, службе локального сохранения интересных страниц, разработанной в качестве альтернативы свободной программы Pocket (теперь принадлежащей Mozilla). Но Wallabag по своему дизайну создаёт только «читаемую» версию статьи вместо полной копии. В некоторых случаях «читаемая версия» на самом деле нечитабельна, и Wallabag иногда не справляется с парсингом. Вместо этого другие инструменты, такие как bookmark-archiver или reminescence, сохраняют скриншот страницы вместе с полным HTML, но, к сожалению, не поддерживают формат WARC, который бы обеспечил ещё более точное воспроизведение.
Печальная правда моего зеркалирования и архивирования заключается в том, что данные умирают. К счастью, архивисты-любители имеют в своём распоряжении инструменты для сохранения интересного контента в интернете. Для тех, кто не хочет заниматься этим самостоятельно, есть Интернет-архив, а также группа ArchiveTeam, которая работает над созданием резервной копии самого Интернет-архива.
Преобразование простых сайтов
Давно прошли дни, когда веб-сайты писались вручную на HTML. Теперь они динамичные и строятся «на лету» с использованием новейших JavaScript, PHP или Python-фреймворков. Как результат, сайты стали более хрупкими: сбой базы данных, ложное обновление или уязвимости могут привести к потере данных. В моей предыдущей жизни в качестве веб-разработчика мне пришлось смириться с мыслью: клиенты ожидают, что веб-сайты будут работать вечно. Это ожидание плохо сочетается с принципом веб-разработки «двигаться быстро и ломать вещи». Работа с системой управления контентом Drupal оказалась особенно сложной в этом отношении, поскольку крупные обновления намеренно нарушают совместимость со сторонними модулями, что подразумевает дорогостоящий процесс обновления, который клиенты редко могут себе позволить. Решение состояло в том, чтобы архивировать эти сайты: взять живой, динамический веб-сайт — и превратить его в простые HTML-файлы, которые любой веб-сервер может выдавать вечно. Этот процесс полезен для ваших собственных динамических сайтов, а также для сторонних сайтов, которые находятся вне вашего контроля, и которые вы хотите защитить.
С простыми или статичными сайтами отлично справляется почтенная программа Wget. Хотя для зеркалирования всего сайта понадобится настоящее заклинание:
$ nice wget --mirror --execute robots=off --no-verbose --convert-links \
--backup-converted --page-requisites --adjust-extension \
--base=./ --directory-prefix=./ --span-hosts \
--domains=www.example.com,example.com http://www.example.com/
Эта команда загружает содержимое веб-страницы, а также выполняет обход всех ссылок в указанных доменах. Перед запуском этого действия на любимом сайте рассмотрите возможные последствия краулинга. Приведённая выше команда намеренно игнорирует правила robots.txt, как сейчас принято у архивистов, и скачивает сайт на максимальной скорости. У большинства краулеров есть опции для паузы между обращениями и ограничения полосы пропускания, чтобы не создавать чрезмерную нагрузку на целевой сайт.
Эта команда также получает «реквизиты страницы», то есть таблицы стилей (CSS), изображения и скрипты. Загруженное содержимое страницы изменяется таким образом, что ссылки указывают уже на локальную копию. Результирующий набор файлов может быть размещён на любом веб-сервере, представляя собой статическую копию исходного веб-сайта.
Но это когда всё идёт хорошо. Любой, кто когда-либо работал с компьютером, знает, что вещи редко идут по плану: есть множество интересных способов сорвать процедуру. Например, некоторое время назад на сайтах было модно ставить блоки с календарём. CMS будет генерировать их «на лету» и отправит краулеры в бесконечный цикл, пытаясь получить всё новые и новые страницы. Хитрые архивариусы могут использовать регулярные выражениям (например, в Wget есть опция
--reject-regex
), чтобы игнорировать проблемные ресурсы. Другой вариант: если доступен интерфейс администрирования веб-сайта — отключить календари, формы входа, формы комментариев и другие динамические области. Как только сайт станет статичным, они всё равно перестанут работать, поэтому есть смысл удалить этот беспорядок с исходного сайта.Кошмар JavaScript
К сожалению, некоторые веб-сайты представляют собой гораздо больше, чем просто HTML. Например, на одностраничных сайтах веб-браузер сам создаёт контент, выполняя небольшую программу JavaScript. Простой пользовательский агент, такой как Wget, будет безуспешно пытаться восстановить значимую статическую копию этих сайтов, поскольку он вообще не поддерживает JavaScript. Теоретически, сайтам следует поддерживать прогрессивное улучшение, чтобы контент и функциональность были доступны без JavaScript, но эти директивы редко соблюдаются, как подтвердит любой, кто использует плагины вроде NoScript или uMatrix.
Традиционные методы архивирования иногда терпят неудачу самым тупым образом. При попытке сделать бэкап местной газеты я обнаружил, что WordPress добавляет строки запросов (например,
?ver=1.12.4
) в конце include. Это сбивает с толку обнаружение content-type на веб-серверах, обслуживающих архив, потому что они для выдачи правильного заголовка Content-Type
полагаются на расширение файла. Когда такой архив загружается в браузер, тот не может загрузить скрипты, что ломает динамические веб-сайты.Поскольку браузер постепенно становится виртуальной машиной для запуска произвольного кода, то методам архивирования, основанным на чистом анализе HTML, следует адаптироваться. Решением этих проблем является запись (и воспроизведение) HTTP-заголовков, доставляемых сервером во время краулинга, и действительно профессиональные архивисты используют именно такой подход.
Создание и отображение файлов WARC
В Интернет-архиве Брюстер Кале и Майк Бёрнер в 1996 году разработали формат ARC (ARChive): способ объединить миллионы небольших файлов, созданных в процессе архивирования. В конечном итоге формат стандартизировали как спецификацию WARC (Web ARChive), выпущенную в качестве стандарта ISO в 2009 году и пересмотренную в 2017 году. Усилия по стандартизации возглавил Международный консорциум по сохранению Интернета (IIPC). Согласно Википедии, это «международная организация библиотек и других организаций, созданных для координации усилий по сохранению интернет-контента для будущего», в неё входят такие члены, как Библиотека Конгресса США и Интернет-архив. Последний использует формат WARC в своём Java-краулере Heritrix.
Файл WARC объединяет в одном сжатом архиве несколько ресурсов, таких как заголовки HTTP, содержимое файла и другие метаданные. Удобно, что этот формат поддерживается и краулером Wget с параметром
--warc
. К сожалению, браузеры не могут напрямую отображать файлы WARC, поэтому для доступа к архиву необходима специальная программа просмотра. Или его придётся конвертировать. Самая простая программа просмотра, которую я нашёл, — pywb, пакет Python. Она запускает простой веб-сервер с интерфейсом типа Wayback Machine для просмотра содержимого файлов WARC. Следующий набор команд отобразит файл WARC на http://localhost:8080/
: $ pip install pywb
$ wb-manager init example
$ wb-manager add example crawl.warc.gz
$ wayback
Кстати, этот инструмент создали разработчики сервиса Webrecorder, который с помощью браузера сохраняет динамическое содержимое страницы.
К сожалению, pywb не умеет загружать WARC-файлы, сгенерированные Wget, потому что он подчиняется некорректным требованиям спецификации WARC 1.0, которые были исправлены в версии 1.1. Пока Wget или pywb не устранят эти проблемы, файлы WARC, созданные Wget, недостаточно надёжны, поэтому лично я начал искать другие альтернативы. Моё внимание привлёк краулер под простым названием crawl. Вот как он запускается:
$ crawl https://example.com/
Программа поддерживает некоторые параметры командной строки, но большинство значений по умолчанию вполне работоспособны: она скачает ресурсы вроде CSS и картинок с других доменов (если не указан флаг
-exclude-related
), но рекурсия не выйдет за пределы указанного хоста. По умолчанию запускается десять параллельных подключений: этот параметр изменяется флагом -c
. Но главное, что результирующие файлы WARC отлично загружаются в pywb.Будущая работа и альтернативы
Есть немало ресурсов по использованию файлов WARC. В частности, есть замена Wget под названием Wpull, специально разработанная для архивирования веб-сайтов. Она имеет экспериментальную поддержку PhantomJS и интеграцию с youtube-dl, что позволит загружать более сложные JavaScript-сайты и скачивать потоковое мультимедиа, соответственно. Программа является основой инструмента архивирования ArchiveBot, разработку которого ведёт «свободный коллектив озорников-архивистов, программистов, писателей и болтунов» из ArchiveTeam в попытке «сохранить историю, прежде чем она исчезнет навсегда». Похоже, что интеграция PhantomJS не так хороша, как хотелось бы, поэтому ArchiveTeam использует ещё кучу других инструментов для зеркалирования более сложных сайтов. Например, snscrape сканирует профили социальных сетей и генерирует списки страниц для отправки в ArchiveBot. Другой инструмент — crocoite, который запускает Chrome в headless-режиме для архивирования сайтов с большим количеством JavaScript.
Эта статья была бы неполной без упоминания «ксерокса сайтов» HTTrack. Аналогично Wget, программа HTTrack создаёт локальные копии сайтов, но, к сожалению, не поддерживает сохранение в WARC. Интерактивные функции могут быть более интересны начинающим пользователям, незнакомым с командной строкой.
В том же духе, во время своих исследований я нашёл альтернативу Wget под названием Wget2 с поддержкой многопоточной работы, которая ускоряет работу программы. Однако здесь отсутствуют некоторые функции Wget, в том числе шаблоны, сохранение в WARC и поддержка FTP, зато добавлены поддержка RSS, кэширование DNS и улучшенная поддержка TLS.
Наконец, моей личной мечтой для таких инструментов было бы интегрировать их с моей существующей системой закладок. В настоящее время я храню интересные ссылки в Wallabag, службе локального сохранения интересных страниц, разработанной в качестве альтернативы свободной программы Pocket (теперь принадлежащей Mozilla). Но Wallabag по своему дизайну создаёт только «читаемую» версию статьи вместо полной копии. В некоторых случаях «читаемая версия» на самом деле нечитабельна, и Wallabag иногда не справляется с парсингом. Вместо этого другие инструменты, такие как bookmark-archiver или reminescence, сохраняют скриншот страницы вместе с полным HTML, но, к сожалению, не поддерживают формат WARC, который бы обеспечил ещё более точное воспроизведение.
Печальная правда моего зеркалирования и архивирования заключается в том, что данные умирают. К счастью, архивисты-любители имеют в своём распоряжении инструменты для сохранения интересного контента в интернете. Для тех, кто не хочет заниматься этим самостоятельно, есть Интернет-архив, а также группа ArchiveTeam, которая работает над созданием резервной копии самого Интернет-архива.