Files
Dmitriy Fofanov a2397f0d39 Функция: добавлен скрипт для исправления внешних ссылок и загрузки ресурсов
- Создан файл `fix-links.js` для обработки загрузки внешних ресурсов и исправления ссылок в HTML-файлах.

- Добавлена ​​конфигурация для разрешенных и пропускаемых доменов, настроек загрузки и механизмов кэширования.

- Реализованы функции для обработки файлов, обработки URL-адресов и одновременных загрузок.

- Введено отслеживание статистики для обработанных файлов, исправленных ссылок и сбоев загрузки.

Задача: инициализация package.json и package-lock.json

- Добавлен файл `package.json` с метаданными проекта и зависимостями.

- Создан файл `package-lock.json` для блокировки версий зависимостей для обеспечения согласованной установки.
2026-03-21 22:07:50 +03:00

216 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mirror-forge
Node.js-проект для зеркалирования сайта в локальную папку `mirror/` с помощью Playwright (headless Chromium).
Проект включает два сценария:
1. `crawl.js` — обходит страницы сайта, сохраняет HTML и ресурсы (CSS/JS/изображения/шрифты и т.д.).
2. `fix-links.js` — пост-обработка уже скачанного зеркала: ищет внешние URL в HTML, догружает недостающие файлы и заменяет ссылки на локальные относительные пути.
---
## Возможности
- Обход внутренних страниц с очередью URL и ограничением по количеству страниц.
- Параллельная загрузка (`CONCURRENCY`) для ускорения зеркалирования.
- Перехват `response` в браузере и сохранение ассетов по `Content-Type`.
- Автоповторы при ошибках (`MAX_RETRIES`).
- Извлечение новых ссылок из финального DOM страницы, а не только из сырого HTML.
- Корректное завершение по `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"`).
---
## Установка
```bash
npm install
npx playwright install
```
Если зависимостей ещё нет, альтернативно:
```bash
npm i playwright
npx playwright install
```
---
## Быстрый старт
### 1) Скачивание сайта
```bash
node crawl.js
```
### 2) Дополнительная фиксация ссылок (опционально)
```bash
node fix-links.js
```
---
## Как устроен `crawl.js`
### Основной поток
1. В очередь добавляется `BASE`.
2. URL обрабатываются батчами по `CONCURRENCY`.
3. Для каждой страницы:
- выполняется `page.goto(..., waitUntil: "domcontentloaded")`;
- даётся дополнительная пауза `WAIT_AFTER_LOAD`;
- выполняется попытка дождаться `networkidle`;
- через `page.on("response")` сохраняются ассеты;
- HTML сохраняется в `mirror/`;
- извлекаются новые ссылки и добавляются в очередь.
4. При ошибках применяются автоповторы до `MAX_RETRIES`.
### Что скачивается
- HTML-документы.
- Скрипты, стили, изображения, шрифты.
- XHR/fetch-ответы (с ограничениями, см. ниже).
### Что фильтруется/ограничивается
- Обход ограничен разрешёнными URL-префиксами (`ALLOWED_URL_PREFIXES`) и origin, вычисленными из них.
- 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_URL_PREFIXES` — список URL-префиксов, которые разрешено обходить/скачивать.
---
## Как формируются локальные пути
- URL-path сохраняется как путь внутри `mirror/`.
- Путь, заканчивающийся на `/`, сохраняется как `.../index.html` (через `index` + расширение).
- Query-строка хешируется (`md5`, 8 символов) и добавляется к имени файла.
- Если у URL нет расширения, оно определяется по `Content-Type`; если определить нельзя — используется `.html`.
- Символы, недопустимые в Windows-путях, заменяются на `_`.
---
## Как устроен `fix-links.js`
`fix-links.js` предназначен для пост-обработки уже скачанного зеркала.
Что делает скрипт:
1. Рекурсивно находит HTML/HTM-файлы в `mirror/`.
2. Извлекает URL из `src/href/srcset/poster/data-src/url(...)`.
3. Для внешних и отсутствующих относительных ссылок:
- проверяет домены по правилам `ALLOWED_DOMAINS` и `SKIP_DOMAINS`;
- скачивает ресурсы в локальную структуру с ограничением по конкурентности;
- заменяет абсолютные ссылки на относительные пути.
4. Ведёт статистику: обработано файлов, исправлено ссылок, скачано/пропущено/ошибки.
Ключевые параметры в `fix-links.js`:
- `MIRROR_DIR` — папка зеркала.
- `DOWNLOAD_TIMEOUT` — таймаут загрузки одного ресурса.
- `DOWNLOAD_CONCURRENCY` — число одновременных загрузок при пост-обработке.
- `MAX_RETRIES` — число повторов загрузки.
- `ALLOWED_DOMAINS` — явно разрешённые домены для скачивания.
- `SKIP_DOMAINS` — домены, которые нужно пропускать.
---
## Логи и статус
### `crawl.js`
- `[start]` — старт обхода.
- `[config]` — активные параметры.
- `[crawled]` — страница сохранена.
- `[retry x/y]` — повторная попытка.
- `[gave up]` — страница не скачана после всех повторов.
- `[done]` — итоговая статистика.
### `fix-links.js`
- `📄 Обрабатываю` — файл в обработке.
- `📥 Скачиваю` / `✅ Скачано` / `❌ Не удалось скачать`.
- При неудачной загрузке исходная ссылка сохраняется, чтобы не превращать рабочий внешний URL в битый локальный путь.
- Итоговый блок `📊 СТАТИСТИКА`.
---
## Ограничения
- Это не «пиксель-в-пиксель офлайн-клон» сложных SPA/PWA.
- Контент, подгружаемый только после действий пользователя (скролл/клик/hover), может не попасть в зеркало.
- Внешние сервисы аналитики/соцсети/CDN могут оставаться внешними ссылками (зависит от доменных правил).
- API-данные с динамическими эндпоинтами не гарантируется получить полностью.
---
## Рекомендации по эксплуатации
- Начинайте с меньшего `MAX_PAGES` и `CONCURRENCY`, затем увеличивайте.
- При частых таймаутах увеличьте `REQUEST_TIMEOUT` и/или `WAIT_AFTER_LOAD`.
- Если сервер ограничивает запросы, уменьшите `CONCURRENCY`.
- Перед массовым запуском проверьте политики сайта (`robots.txt`, Terms of Service) и правовые ограничения.
---
## Типичный workflow
1. Настроить `BASE` и `ALLOWED_URL_PREFIXES` в `crawl.js`.
2. Запустить `node crawl.js`.
3. Проверить структуру `mirror/`.
4. При необходимости запустить `node fix-links.js`.
5. Открывать локальные HTML из `mirror/` для анализа/архивации/офлайн-просмотра.
---
## Структура проекта
```text
.
├─ crawl.js
├─ fix-links.js
├─ package.json
├─ README.md
└─ mirror/ # создаётся после запуска
```
---
## Лицензия
ISC (см. `package.json` и `LICENSE`).