master
- Создан новый файл `.gitignore` для исключения ненужных файлов и каталогов. - Добавлен файл `LICENSE` с информацией об авторских правах и условиях использования. - Реализован `crawl.js` для зеркалирования веб-сайта с использованием Playwright, включая функции обработки ссылок и ресурсов. - Разработан `fix-links.js` для исправления внешних ссылок в HTML-файлах, чтобы они указывали на локальные ресурсы. - Инициализированы `package.json` и `package-lock.json` с Playwright в качестве зависимости.
DFWebJS_DownLoad
Node.js-проект для зеркалирования сайта в локальную папку mirror/ с помощью Playwright (headless Chromium).
Проект включает два сценария:
crawl.js— обходит страницы сайта, сохраняет HTML и ресурсы (CSS/JS/изображения/шрифты и т.д.).fix-links.js— пост-обработка уже скачанного зеркала: ищет внешние URL в HTML, догружает недостающие файлы и заменяет ссылки на локальные относительные пути.
Возможности
- Обход внутренних страниц с очередью URL и ограничением по количеству страниц.
- Параллельная загрузка (
CONCURRENCY) для ускорения зеркалирования. - Перехват
responseв браузере и сохранение ассетов поContent-Type. - Автоповторы при ошибках (
MAX_RETRIES). - Корректное завершение по
Ctrl+C(graceful shutdown). - Нормализация путей для Windows (замена недопустимых символов).
- Поддержка query-строк через хеширование имени файла, чтобы избежать перезаписи.
- Опциональная замена абсолютных ссылок в HTML на относительные (
FIX_LINKS). - Принудительное сохранение HTML в UTF-8 (
<meta charset="utf-8">).
Стек и требования
- Node.js 18+
- npm
- Playwright (
playwright) - ОС: Windows / Linux / macOS
В
package.jsonпроект работает в режиме ES Modules ("type": "module").
Установка
npm install
npx playwright install
Если зависимостей ещё нет, альтернативно:
npm i playwright
npx playwright install
Быстрый старт
1) Скачивание сайта
node crawl.js
2) Дополнительная фиксация ссылок (опционально)
node fix-links.js
Как устроен crawl.js
Основной поток
- В очередь добавляется
BASE. - URL обрабатываются батчами по
CONCURRENCY. - Для каждой страницы:
- выполняется
page.goto(..., waitUntil: "domcontentloaded"); - даётся дополнительная пауза
WAIT_AFTER_LOAD; - выполняется попытка дождаться
networkidle; - через
page.on("response")сохраняются ассеты; - HTML сохраняется в
mirror/; - извлекаются новые ссылки и добавляются в очередь.
- выполняется
- При ошибках применяются автоповторы до
MAX_RETRIES.
Что скачивается
- HTML-документы.
- Скрипты, стили, изображения, шрифты.
- XHR/fetch-ответы (с ограничениями, см. ниже).
Что фильтруется/ограничивается
- Обход ограничен разрешёнными origin (
ALLOWED_ORIGINS). - JSON-ответы без расширения
.jsonпропускаются в загрузчике ассетов, чтобы не перезаписывать HTML. - URL с неподдерживаемыми схемами (
data:,javascript:,mailto:,tel:,blob:) игнорируются. - Ассеты (по расширению) не попадают в очередь страниц.
Конфигурация crawl.js
Ключевые параметры находятся вверху файла:
BASE— стартовый URL обхода.OUT_DIR— папка вывода (по умолчаниюmirror).MAX_PAGES— лимит страниц для обхода.CONCURRENCY— количество одновременно открытых вкладок.WAIT_AFTER_LOAD— задержка послеdomcontentloaded.MAX_RETRIES— число повторных попыток для страницы.REQUEST_TIMEOUT— таймаут навигацииpage.goto.USER_AGENT— User-Agent браузера.FIX_LINKS— включить замену ссылок в HTML на относительные в момент сохранения.ALLOWED_ORIGINS— список origin, которые разрешено обходить/скачивать.
Как формируются локальные пути
- URL-path сохраняется как путь внутри
mirror/. - Путь, заканчивающийся на
/, сохраняется как.../index.html(черезindex+ расширение). - Query-строка хешируется (
md5, 8 символов) и добавляется к имени файла. - Если у URL нет расширения, оно определяется по
Content-Type; если определить нельзя — используется.html. - Символы, недопустимые в Windows-путях, заменяются на
_.
Как устроен fix-links.js
fix-links.js предназначен для пост-обработки уже скачанного зеркала.
Что делает скрипт:
- Рекурсивно находит HTML/HTM-файлы в
mirror/. - Извлекает URL из
src/href/srcset/poster/data-src/url(...). - Для внешних ссылок:
- проверяет домены по правилам
ALLOWED_DOMAINSиSKIP_DOMAINS; - скачивает ресурсы в локальную структуру;
- заменяет абсолютные ссылки на относительные пути.
- проверяет домены по правилам
- Ведёт статистику: обработано файлов, исправлено ссылок, скачано/пропущено/ошибки.
Ключевые параметры в fix-links.js:
MIRROR_DIR— папка зеркала.DOWNLOAD_TIMEOUT— таймаут загрузки одного ресурса.MAX_RETRIES— число повторов загрузки.ALLOWED_DOMAINS— явно разрешённые домены для скачивания.SKIP_DOMAINS— домены, которые нужно пропускать.
Логи и статус
crawl.js
[start]— старт обхода.[config]— активные параметры.[crawled]— страница сохранена.[retry x/y]— повторная попытка.[gave up]— страница не скачана после всех повторов.[done]— итоговая статистика.
fix-links.js
📄 Обрабатываю— файл в обработке.📥 Скачиваю/✅ Скачано/❌ Не удалось скачать.- Итоговый блок
📊 СТАТИСТИКА.
Ограничения
- Это не «пиксель-в-пиксель офлайн-клон» сложных SPA/PWA.
- Контент, подгружаемый только после действий пользователя (скролл/клик/hover), может не попасть в зеркало.
- Внешние сервисы аналитики/соцсети/CDN могут оставаться внешними ссылками (зависит от доменных правил).
- API-данные с динамическими эндпоинтами не гарантируется получить полностью.
Рекомендации по эксплуатации
- Начинайте с меньшего
MAX_PAGESиCONCURRENCY, затем увеличивайте. - При частых таймаутах увеличьте
REQUEST_TIMEOUTи/илиWAIT_AFTER_LOAD. - Если сервер ограничивает запросы, уменьшите
CONCURRENCY. - Перед массовым запуском проверьте политики сайта (
robots.txt, Terms of Service) и правовые ограничения.
Типичный workflow
- Настроить
BASEиALLOWED_ORIGINSвcrawl.js. - Запустить
node crawl.js. - Проверить структуру
mirror/. - При необходимости запустить
node fix-links.js. - Открывать локальные HTML из
mirror/для анализа/архивации/офлайн-просмотра.
Структура проекта
.
├─ crawl.js
├─ fix-links.js
├─ package.json
├─ README.md
└─ mirror/ # создаётся после запуска
Лицензия
ISC (см. package.json и LICENSE).
Description
Node.js-проект для зеркалирования сайта в локальную папку
mirror/ с помощью Playwright (headless Chromium).
Languages
JavaScript
100%