Files
Web-Parser-Constructor/docs/design-spec.md
T
2026-10-01 00:28:16 +10:00

27 KiB

Архив первоначального проекта. С 2026-10-01 Rio удалён: приложение использует FastAPI, Jinja2 и HTML/CSS/JavaScript. Актуальное описание — в README.md.

Спецификация учебного сайта для парсинга данных

Документ описывает первую версию сайта для занятий по основам ML, в том числе для психологов. Преподаватель загружает данные неизвестной заранее структуры и публикует их в разных представлениях. Студенты собирают опубликованные записи обычными HTTP-парсерами или браузерной автоматизацией. Реализация начнётся после согласования спецификации и плана.

Согласованные требования

  • Один преподаватель, закрытый кабинет на Python Rio, вход по логину и паролю без регистрации.
  • Публичные учебные страницы без аккаунтов студентов.
  • Импорт CSV, JSON и JSONL через кабинет.
  • Таблицы, карточки, сообщения и заполненные анкеты; сбор новых ответов не входит в первую версию.
  • Два режима доступа к одному набору: HTML для requests, BeautifulSoup и Scrapy; динамический Rio для Playwright и Selenium.
  • Предпросмотр, черновики, публикация и снятие с публикации.
  • Docker Compose, постоянное хранение данных и возможность разместить приложение на выбранном сервере.
  • Современное адаптивное оформление и сохранение исходных пропусков и неоднородных значений.

Описанные ниже конкретные правила, пределы и адреса являются предлагаемыми решениями для первой версии.

Архитектура

Один Python-процесс и контейнер обслуживают Rio и HTML-маршруты через FastAPI. Кабинет расположен под /admin, динамические страницы под /interactive, серверные HTML-страницы под /html. Конкретную интеграцию проверяем на закреплённой версии rio-ui до разработки остальных экранов.

Импорт, хранение, настройка полей и выборка записей образуют общее ядро. Оба механизма отображения получают одинаковые записи и конфигурацию; логика фильтрации и пагинации не дублируется. HTML генерируется сервером из шаблонов с экранированием текста. Полезное содержимое присутствует в исходном HTTP-ответе без запуска JavaScript.

SQLite хранит наборы, записи, настройки представлений, черновики и публикации. Исходные файлы находятся отдельно в постоянном каталоге. Данные пользователя не размещаются в публичном каталоге статических файлов. Схема базы имеет версию и последовательные миграции.

Модули разделяются по ответственности: импорт; модель данных и хранилище; публикации; авторизация; кабинет Rio; динамические представления Rio; HTML-маршруты и шаблоны. Запуск приложения не требует pandas для каждого запроса.

Путь преподавателя и экраны

  1. Вход. Логин и пароль, понятная ошибка без раскрытия существования пользователя, выход из кабинета.
  2. Каталог. Название набора, число записей, статус, время изменения и действия «Редактировать», «Предпросмотр», «Опубликовать», «Снять с публикации».
  3. Импорт. Выбор файла, параметры чтения, список ошибок и первые 20 записей. После подтверждения создаётся черновик; исходный файл сохраняется.
  4. Настройка. Название, описание, адрес набора, представления, поля, подписи и количество записей на странице.
  5. Предпросмотр. Проверка обоих режимов с реальными данными черновика. Предпросмотр доступен только преподавателю.
  6. Публикация. Итоговая проверка, создание версии и ссылки на HTML и Rio для каждого включённого представления.

Изменения сохраняются явной кнопкой. При уходе с несохранёнными изменениями показывается предупреждение. Замена файла создаёт новую редакцию черновика и требует повторной проверки соответствия полей.

Правила импорта

Начальные настраиваемые ограничения: файл до 25 МиБ, до 50 000 записей, глубина JSON до 20 уровней. Превышение вызывает понятную ошибку до публикации. Это границы приёма, а не обещание конкретной скорости работы; производительность проверяется отдельно на целевом оборудовании.

CSV

Поддерживаются UTF-8 с BOM и без него, а также выбираемая Windows-1251. Преподаватель может указать запятую, точку с запятой или табуляцию; автоматическое предположение видно в предпросмотре. Первая строка содержит заголовки. Пустые и повторяющиеся заголовки блокируют импорт с указанием колонок. Поддерживаются кавычки, разделители и переводы строк внутри значений.

Значения сохраняются строками, включая ведущие нули, даты и десятичные запятые. Пустая ячейка остаётся пустой строкой. Ошибка количества полей или синтаксиса сообщает позицию; повреждённые строки не пропускаются молча.

JSON

Вход — массив объектов, одиночный объект как одна запись либо объект, внутри которого преподаватель выбирает массив объектов. Выбор вложенного массива не выполняется скрыто. Массив скалярных значений и смесь объектов со скалярами отклоняются с объяснением поддерживаемой структуры. Повторяющиеся ключи объектов и нестандартные NaN/Infinity отклоняются, чтобы исключить потерю значений.

Объекты и массивы сохраняются вложенными. Поля выбираются деревом структуры; внутри конфигурации используются однозначные пути JSON Pointer. Отсутствующее поле, null, пустая строка, false и 0 остаются различимыми.

JSONL

Каждая непустая строка содержит один JSON-объект. Пустые строки игнорируются с отображением их количества. Некорректная строка блокирует сохранение импорта; сообщение содержит номер строки и причину. Используется UTF-8 с допустимым BOM в начале файла.

Общие правила

Порядок записей сохраняется. Дубликаты и пропуски автоматически не удаляются. Каждая запись получает внутренний идентификатор, который не зависит от наличия уникального поля в файле и стабилен внутри опубликованной версии. Поля определяются по всему принятому набору, а не только по предпросмотру. Если необязательного поля нет в части записей, это отражается при настройке.

Некорректный импорт не заменяет существующие данные. Файлы хранятся под внутренними именами; пользовательское имя используется только для отображения. Загруженное содержимое считается данными и не исполняется.

Представления

Вид Настройка Отображение
Таблица Произвольные выбранные поля, подписи и порядок колонок Заголовки и строки, переходы на страницу записи
Карточки Заголовок, необязательное описание и дополнительные поля Сетка карточек с переходом к деталям
Сообщения Текст, необязательные автор и дата, дополнительные поля Линейная лента сообщений без веток обсуждений
Анкеты Идентификатор или заголовок участника, выбранные ответы Заполненный бланк с вопросами и значениями

Для анкет поддерживаются два явных способа настройки: колонки как ответы с подписями вопросов либо вложенный массив пар «вопрос — ответ», для которого задаются пути к обоим значениям. Нет расчёта шкал, интерпретации результатов или конструктора опросов.

Один набор может включать несколько представлений с независимыми настройками. Отсутствие необходимого поля, например текста сообщения, блокирует публикацию этого представления. Необязательные поля можно не назначать. Объекты и массивы в обычной ячейке выводятся как экранированный JSON; специальный способ вывода вложенных анкет применяется только при явной настройке.

Для отсутствующего значения и null используются разные видимые обозначения; пустая строка остаётся пустой. Их семантика также доступна через атрибут состояния значения в HTML. Исходный тип не определяется по внешнему виду текста.

Учебные режимы

Пример адреса HTML: /html/study-a/v/1/table?page=2. Пример Rio: /interactive/study-a/v/1/table. У каждого представления есть собственный сегмент адреса. В ссылках содержится версия публикации.

Обычный HTML

Таблицы используют table, thead, tbody, th и td. Остальные представления используют обычные семантические блоки, заголовки и ссылки. Записи и значения имеют документированные устойчивые CSS-классы и идентификаторы. Ни данные, ни переходы не требуют JavaScript, WebSocket или особого User-Agent.

Предлагаемые размеры страниц: 10, 25, 50, 100; по умолчанию 25. Порядок соответствует импорту. Страницы доступны через реальные ссылки. Нецелый, отрицательный или нулевой номер возвращает 400; номер за пределами набора — 404. Публикация пустого набора запрещена. Индивидуальные страницы записей дают упражнение на переходы по ссылкам.

Динамический Rio

Первая порция содержит настроенное число записей. Кнопка «Загрузить ещё» добавляет следующую порцию, показывает состояние загрузки и исчезает после последней записи. Повторные нажатия во время запроса не создают дубликатов.

Преподаватель выбирает одно текстовое поле для поиска и, при необходимости, одно поле категориального фильтра. Изменение фильтра сбрасывает список и позицию загрузки. Доступны состояния ожидания, отсутствия результатов и ошибки. Динамические упражнения не включают CAPTCHA, искусственные задержки или противодействие парсерам.

В HTML те же фильтры передаются query-параметрами и применяются сервером. Для обоих режимов поиск — регистронезависимое вхождение в выбранное текстовое поле, категориальный фильтр — точное совпадение значения. Результат всегда сохраняет исходный порядок.

Публичная выдача исходного файла и отдельный JSON API не включаются в первую версию. Это учебная организация доступа, а не гарантия, что видимые данные невозможно получить другим способом. Сервер отдаёт только поля, включённые в соответствующее представление; скрытые поля не передаются клиенту внутри полного объекта записи.

Публикации и сохранность

Публикация атомарно создаёт неизменяемый снимок записей и настроек всех включённых представлений. Неудачная операция оставляет предыдущую публикацию доступной. Изменения черновика не затрагивают опубликованные версии.

Повторная публикация создаёт новый номер и новые ссылки. Старые ссылки продолжают показывать прежний материал до снятия соответствующей версии с публикации. Это предотвращает изменение данных между запросами студенческого парсера. Снятая версия возвращает 404 в обоих режимах; черновик остаётся у преподавателя. В первой версии достаточно снятия с публикации, без интерфейса безвозвратного удаления истории.

Внешний вид

Интерфейс на русском языке: светлый фон, тёмный читаемый текст, спокойный сине-зелёный акцент, единые размеры отступов и контрастные состояния элементов. Кабинет использует боковую навигацию на широком экране и компактную на узком. Основные действия визуально выделены, технические параметры появляются только там, где нужны для выбора.

Таблицы прокручиваются горизонтально, длинные сообщения переносятся, анкеты сохраняют связь вопроса и ответа. Карточки перестраиваются в одну колонку на телефоне. HTML и Rio имеют общий визуальный стиль, но не требуют идентичной внутренней разметки. Шрифты и необходимые статические ресурсы поставляются с приложением, чтобы интерфейс не зависел от внешнего CDN.

Авторизация и Docker

Учётные данные задаются при развёртывании: имя пользователя и хеш пароля через переменные окружения или файл секрета. Открытая регистрация и стандартный встроенный пароль отсутствуют. Инструкция содержит способ создания хеша и смены пароля. Вход ограничивается по частоте; сессия защищает все операции кабинета, предпросмотр и доступ к исходным файлам. Изменяющие операции проверяют подлинность сессии и защищены от CSRF. Пароли и данные анкет не попадают в журналы запросов.

Контейнер запускается непривилегированным пользователем, слушает порт 8080 и использует /data как постоянный том. SQLite и исходные файлы находятся в этом томе. Порт хоста настраивается через Compose; доступны проверка работоспособности и корректное завершение процесса. При отсутствии настроек входа приложение сообщает ошибку запуска, а не открывает кабинет без защиты.

HTTPS завершается на внешнем reverse proxy, который передаёт HTTP и WebSocket. Поддерживаемый вариант первой версии — приложение в корне отдельного домена; размещение под произвольным префиксом URL не обещается. При HTTPS cookie сессии получает Secure; для локального HTTP есть явная настройка. Работа нескольких реплик с общей SQLite в первую версию не входит.

В комплект входят Dockerfile, compose.yaml, пример переменных окружения без секретов и инструкция запуска, обновления и резервного копирования. Простой согласованный способ резервного копирования — остановить контейнер и скопировать весь том; восстановление проверяется отдельно. Данные не встраиваются в образ как изменяемое хранилище.

Демонстрационные данные

Старый хоккейный CSV сохраняется в качестве примера таблицы. Дополнительные небольшие синтетические наборы демонстрируют сообщения, карточки и оба формата заполненных анкет. Примеры включают Unicode, пустые значения, длинный текст и повторяющиеся значения. Демонстрационные наборы импортируются явно и не перезаписывают рабочие данные при перезапуске.

Старый NiceGUI-проект остаётся источником примера, а не основой нового интерфейса. Совместимость старого адреса ?pageNum= не входит в первую версию.

Проверка и критерии готовности

  1. Преподаватель импортирует каждый поддерживаемый формат без редактирования кода; ошибки показывают причину и расположение.
  2. Назначение полей работает с произвольными заголовками и вложенными значениями. Несовместимые настройки нельзя опубликовать.
  3. Для одного набора включаются несколько представлений, и каждое доступно в обоих режимах.
  4. Парсер requests и BeautifulSoup собирает все видимые записи по ссылкам и страницам без пропусков и дублей. Проверяются значения, а не только количество.
  5. Парсер Playwright получает те же записи, используя динамическую загрузку и фильтры. При отсутствии фильтров порядок совпадает с HTML.
  6. Редактирование и повторная публикация не изменяют старые опубликованные ссылки. Черновики, исходные файлы и скрытые поля недоступны студентам.
  7. Замена контейнера сохраняет данные; резервная копия восстанавливается в чистом окружении.
  8. Через браузер проверяются все четыре представления, узкий экран, длинные тексты, пустые значения, вход и ошибки загрузки.
  9. Контейнер собирается из документированной команды; проверяются старт, HTTP, WebSocket, том и завершение.

Примеры парсеров передаются преподавателю отдельными файлами, без автоматической публикации решений на учебном сайте. Версии Python и библиотек закрепляются после проверки совместимости Rio, FastAPI и контейнера. До этого документация текущего Rio подтверждает направление интеграции, но не заменяет проверку установленной версии.

Границы первой версии

Не входят: несколько преподавателей, аккаунты студентов, сбор ответов, оценивание работ, обучение моделей, произвольный редактор HTML, ветки комментариев, импорт по внешним URL, публичный API выгрузки, горизонтальное масштабирование и автоматическое размещение на конкретном сервере. Объём первой версии заканчивается работающим проверенным Docker-пакетом и инструкциями.

Последовательность дальнейшей работы

После проверки этой спецификации готовится отдельный план реализации с файлами, зависимостями, этапами и проверками. Порядок: совместимость Rio и HTML в одном приложении; хранение и вход; импорт; настройка представлений; публикации и оба режима; оформление; парсеры и проверка Docker. Продуктовый код в рамках подготовки спецификации не изменяется.

Основания технических решений

Изученный старый проект расположен в P:\Coding\Python\NetologyWebParserSite\HockeyTeamParse: NiceGUI, pandas, один CSV, страницы по 25 строк, Docker Compose. Окружение с установленным Rio в изученном проекте не найдено.

Официальные источники Rio, проверенные при обсуждении: App и as_fastapi, сервер и динамическая загрузка интерфейса. Архитектура этого документа является проектным предложением, а не утверждением о готовности перечисленных функций в старом приложении.