Skip to content

Repository files navigation

Python 3.11+PoetryCode style: ruffType checked: mypyDockerPydanticSQLAlchemyStructlogpre-commitLicense: MIT



📄 Document Crawler

A production-ready document crawler with full-text search capabilities. Extracts text from various formats, handles nested archives, and provides powerful FTS.


📋 Table of Contents


✨ Features

  • Deep Crawling: Recursive directory traversal with hidden file support
  • Archive Extraction: Automatic unpacking of ZIP, RAR, 7z (including nested archives up to 3 levels)
  • Multi-format Support: Text extraction from 10+ document formats
  • Full-Text Search: SQLite FTS5 with automatic indexing and triggers
  • Dual Output: Results saved to both SQLite (for search) and CSV (for analysis)
  • Production Ready:
    • Full type hints with mypy --strict
    • Structured logging with structlog
    • Clean Architecture with clear separation of concerns
    • Docker support

📑 Supported Formats

FormatStatusLibrary/ToolNotes
PDFPyPDF2Text extraction from all pages
DOCXpython-docxParagraphs and tables
DOC⚠️antiword/catdocNot tested. Not applicable in Docker. Requires external utilities*
XLSXopenpyxlAll sheets and cells
XLSxlrdLegacy Excel format
TXTbuilt-inAuto-encoding detection
MDTextParserMarkdown as plain text
JSONTextParserJSON as plain text
XMLTextParserXML as plain text
HTMLTextParserHTML as plain text
ZIPpatoolNested archives supported
RAR⚠️patool + unrarRequires external unrar* or use via docker
7Z⚠️patool + p7zipRequires external p7zip* or use via docker

*External utilities need to be installed separately in the system (see External Dependencies).


🚀 Quick Start

Prerequisites

  • Python 3.11+
  • Poetry
  • Your files to crawl (place them in data/storage/)

Installation

# Clone the repository
git clone https://github.com/script-logic/document-crawler.git
cd document-crawler
# Create .env file from example
cp .env.example .env
# Install with poetry
poetry install

Basic Usage

# Generate sample test files (optional)
poetry run python run_crawler.py generate-samples
# Crawl storage directory
poetry run python run_crawler.py crawl
# Search indexed documents
poetry run python run_crawler.py search "your query"

📁 Project Structure

├── app/ # Main application package
│ ├── application/ # Use cases (business logic)
│ │ └── use_cases/
│ │ ├── crawl.py # Crawling orchestration
│ │ └── search.py # Search orchestration
│ ├── config/ # Configuration
│ │ └── config.py # Pydantic settings
│ ├── domain/ # Domain models
│ │ ├── entities/ # Document entity
│ │ └── value_objects/ # FileHash value object
│ ├── infrastructure/ # External concerns
│ │ ├── crawler/ # File scanning & archives
│ │ ├── database/ # SQLAlchemy models & repository
│ │ ├── logger/ # Structured logging
│ │ └── parsers/ # Document parsers (PDF, DOCX, etc.)
│ └── utils/ # Helpers (Singleton)
├── data/ # Storage and output
│ ├── storage/ # Place your files here
│ └── output/ # Generated CSV files
├── tests/ # Test suite
├── .env.example # Example environment
├── docker-compose.yml # Docker setup
├── pyproject.toml # Project metadata
└── run_crawler.py # Entry point

⚙️ Configuration

Configure via .env file (copy from .env.example):

# LoggingLOGGER__APP_NAME=Document CrawlerLOGGER__DEBUG=trueLOGGER__LOG_LEVEL=INFOLOGGER__ENABLE_FILE_LOGGING=falseLOGGER__LOGS_DIR=logs# Storage pathsCRAWLER__STORAGE_PATH=data/storageCRAWLER__OUTPUT_CSV_PATH=data/output/crawled_files.csv# Crawler settingsCRAWLER__MAX_FILE_SIZE_MB=100CRAWLER__SKIP_HIDDEN=trueCRAWLER__EXTRACT_ARCHIVES=trueCRAWLER__MAX_ARCHIVE_DEPTH=3# Supported extensionsCRAWLER__EXTRACT_TEXT_FROM=["pdf", "docx", "xlsx", "doc", "xls", "txt", "md", "json", "xml", "html"]CRAWLER__ARCHIVE_EXTENSIONS=["zip", "rar", "7z"]# DatabaseDATABASE__PATH=db/crawler.dbDATABASE__FTS_ENABLED=true

🎯 Usage

Commands

# Crawl storage directory
python run_crawler.py crawl [OPTIONS]
Options:
--storage PATH Path to storage directory (default: data/storage)
--output PATH Path to output CSV (default: data/output/crawled_files.csv)
--limit N Maximum number of files to process
--no-archives Don't extract archives# Search indexed documentspython run_crawler.py search QUERY [OPTIONS]Options: --limit N Maximum results to return (default: 20) --type TYPE Filter by document type (pdf, docx, xlsx, txt)# Show database statisticspython run_crawler.py stats# Generate test filespython run_crawler.py generate-samples [OPTIONS]Options: --output PATH Output directory (default: tests/fixtures/samples) --count N Number of samples per type (default: 5)

Examples

# Full crawl
poetry run python run_crawler.py crawl
# Crawl with limit (for testing)
poetry run python run_crawler.py crawl --limit 100
# Search with filters
poetry run python run_crawler.py search "financial report" --type pdf --limit 10
# Complex FTS query (phrases, NEAR operator)
poetry run python run_crawler.py search '"tax planning" NEAR/5 client'# Database stats
poetry run python run_crawler.py stats
# Generate 10 test files
poetry run python run_crawler.py generate-samples --count 10

🏗 Architecture

  • Domain Layer: Business logic, no external dependencies (except pydantic)
  • Application Layer: Orchestrates use cases, depends on abstractions
  • Infrastructure Layer: Implements interfaces, handles external concerns
  • Dependency Injection: All components receive their dependencies
  • Repository Pattern: Abstracts data storage
  • Factory Pattern: Creates appropriate parsers based on file type

🔧 External Dependencies

Some formats require system-level utilities:

FormatRequired ToolInstallation
RAR archivesunrarWindows: Install WinRAR or 7-Zip
Linux: sudo apt-get install unrar
macOS: brew install unrar
7Z archivesp7zipWindows: Install 7-Zip
Linux: sudo apt-get install p7zip-full
macOS: brew install p7zip
DOC filesantiword or catdocWindows: https://github.com/rsdoiel/antiword
Linux: sudo apt-get install antiword
macOS: brew install antiword

Note: These are external executables, not Python packages. They must be installed in your system PATH. Please note: these external tools may not be available on your system even after following the installation instructions above.


🛠 Development

Setup

# Install with dev dependencies
poetry install --with dev
# Install pre-commit hooks
pre-commit install

Available Make Commands

make run-crawl # Run crawler
make run-search QUERY=... # Search documents
make run-stats # Show database stats
make run-generate-samples # Generate test files
make up # Start Docker container
make down # Stop Docker container
make lint # Run ruff and mypy
make format # Format code with ruff
make clean # Clean cache files

Code Quality

  • Ruff: Fast Python linter (replaces flake8, isort)
  • mypy: Strict type checking with --strict
  • pre-commit: Automated checks before commits

Docker

# Build and run
docker-compose up
# Run with custom command
docker-compose run --rm crawler python run_crawler.py search "query"# Rebuild
docker-compose build --no-cache

📝 License

MIT License - feel free to use and modify.





📄 Краулер документов

Продакшен-реди краулер документов с полнотекстовым поиском. Извлекает текст из различных форматов, обрабатывает вложенные архивы и предоставляет мощный FTS.


📋 Содержание


✨ Возможности

  • Глубокий обход: Рекурсивный обход директорий с поддержкой скрытых файлов
  • Извлечение из архивов: Автоматическая распаковка ZIP, RAR, 7z (включая вложенные архивы до 3 уровней)
  • Мультиформатность: Извлечение текста из 10+ форматов документов
  • Полнотекстовый поиск: SQLite FTS5 с автоматическим индексированием и триггерами
  • Двойной вывод: Сохранение в SQLite (для поиска) и CSV (для анализа)
  • Готов к продакшену:
    • Полная типизация (mypy --strict)
    • Структурированное логирование (structlog)
    • Чистая архитектура
    • Поддержка Docker

📑 Поддерживаемые форматы

ФорматСтатусБиблиотека/УтилитаПримечания
PDFPyPDF2Извлечение текста со всех страниц
DOCXpython-docxПараграфы и таблицы
DOC⚠️antiword/catdocНе протестировано. Не используется в docker. Требует внешние утилиты*
XLSXopenpyxlВсе листы и ячейки
XLSxlrdСтарый формат Excel
TXTвстроенныйАвтоопределение кодировки
MDTextParserMarkdown как plain text
JSONTextParserJSON как plain text
XMLTextParserXML как plain text
HTMLTextParserHTML как plain text
ZIPpatoolПоддержка вложенных архивов
RAR⚠️patool + unrarТребует внешний unrar* или используйте docker
7Z⚠️patool + p7zipТребует внешний p7zip* или используйте docker

*Внешние утилиты устанавливаются отдельно в систему (см. Внешние зависимости).


🚀 Быстрый старт

Требования

  • Python 3.11+
  • Poetry
  • Ваши файлы для индексации (поместите в data/storage/)

Установка

# Клонировать репозиторий
git clone https://github.com/script-logic/document-crawler.git
cd document-crawler
# Создать .env файл из примера
cp .env.example .env
# Установка с poetry
poetry install

Базовое использование

# Сгенерировать тестовые файлы (опционально)
poetry run python run_crawler.py generate-samples
# Запустить краулер
poetry run python run_crawler.py crawl
# Поиск по индексированным документам
poetry run python run_crawler.py search "ваш запрос"

📁 Структура проекта

├── app/ # Основной пакет приложения
│ ├── application/ # Use cases (бизнес-логика)
│ │ └── use_cases/
│ │ ├── crawl.py # Оркестрация краулинга
│ │ └── search.py # Оркестрация поиска
│ ├── config/ # Конфигурация
│ │ └── config.py # Pydantic настройки
│ ├── domain/ # Доменные модели
│ │ ├── entities/ # Сущность Document
│ │ └── value_objects/ # Value object FileHash
│ ├── infrastructure/ # Внешние зависимости
│ │ ├── crawler/ # Сканирование и архивы
│ │ ├── database/ # SQLAlchemy модели и репозиторий
│ │ ├── logger/ # Структурированное логирование
│ │ └── parsers/ # Парсеры документов
│ └── utils/ # Вспомогательные утилиты
├── data/ # Хранилище и вывод
│ ├── storage/ # Сюда класть файлы
│ └── output/ # Сгенерированные CSV
├── tests/ # Тесты
├── .env.example # Пример .env
├── docker-compose.yml # Docker настройки
├── pyproject.toml # Метаданные проекта
└── run_crawler.py # Точка входа

⚙️ Конфигурация

Настройка через .env файл (скопируйте из .env.example):

# ЛогированиеLOGGER__APP_NAME=Document CrawlerLOGGER__DEBUG=trueLOGGER__LOG_LEVEL=INFOLOGGER__ENABLE_FILE_LOGGING=falseLOGGER__LOGS_DIR=logs# Пути к даннымCRAWLER__STORAGE_PATH=data/storageCRAWLER__OUTPUT_CSV_PATH=data/output/crawled_files.csv# Настройки краулераCRAWLER__MAX_FILE_SIZE_MB=100CRAWLER__SKIP_HIDDEN=trueCRAWLER__EXTRACT_ARCHIVES=trueCRAWLER__MAX_ARCHIVE_DEPTH=3# Поддерживаемые расширенияCRAWLER__EXTRACT_TEXT_FROM=["pdf", "docx", "xlsx", "doc", "xls", "txt", "md", "json", "xml", "html"]CRAWLER__ARCHIVE_EXTENSIONS=["zip", "rar", "7z"]# База данныхDATABASE__PATH=db/crawler.dbDATABASE__FTS_ENABLED=true

🎯 Использование

Команды

# Краулинг директории
python run_crawler.py crawl [ОПЦИИ]
Опции:
--storage PATH Путь к директории с файлами (по умолч.: data/storage)
--output PATH Путь к выходному CSV (по умолч.: data/output/crawled_files.csv)
--limit N Максимальное количество файлов
--no-archives Не обрабатывать архивы
# Поиск по индексированным документам
python run_crawler.py search ЗАПРОС [ОПЦИИ]
Опции:
--limit N Максимум результатов (по умолч.: 20)
--type TYPE Фильтр по типу (pdf, docx, xlsx, txt)
# Статистика БД
python run_crawler.py stats
# Генерация тестовых файлов
python run_crawler.py generate-samples [ОПЦИИ]
Опции:
--output PATH Директория для сохранения (по умолч.: tests/fixtures/samples)
--count N Количество файлов каждого типа (по умолч.: 5)

Примеры

# Полный краулинг
poetry run python run_crawler.py crawl
# Краулинг с лимитом (для тестирования)
poetry run python run_crawler.py crawl --limit 100
# Поиск с фильтрами
poetry run python run_crawler.py search "финансовый отчет" --type pdf --limit 10
# Сложный FTS запрос (фразы, NEAR оператор)
poetry run python run_crawler.py search '"налоговое планирование" NEAR/5 клиент'# Статистика БД
poetry run python run_crawler.py stats
# Генерация 10 тестовых файлов
poetry run python run_crawler.py generate-samples --count 10

🏗 Архитектура

  • Доменный слой: Бизнес-логика, нет внешних зависимостей (кроме pydantic для удобства валидации)
  • Слой приложения: Оркестрирует use cases, зависит от абстракций
  • Инфраструктурный слой: Реализует интерфейсы, работает с внешними системами
  • Внедрение зависимостей: Все компоненты получают зависимости через конструктор
  • Репозиторий: Абстрагирует хранение данных
  • Фабрика: Создает парсеры на основе типа файла

🔧 Внешние зависимости

Некоторые форматы требуют системных утилит:

ФорматТребуемая утилитаУстановка
RAR архивыunrarWindows: Установите WinRAR или 7-Zip
Linux: sudo apt-get install unrar
macOS: brew install unrar
7Z архивыp7zipWindows: Установите 7-Zip
Linux: sudo apt-get install p7zip-full
macOS: brew install p7zip
DOC файлыantiword или catdocWindows: https://github.com/rsdoiel/antiword
Linux: sudo apt-get install antiword
macOS: brew install antiword

Важно: Это внешние исполняемые файлы, а не Python-пакеты. Они должны быть установлены в системе и доступны в PATH. Примечание: эти внешние инструменты могут отсутствовать в вашей системе или быть недоступны, даже если вы следовали инструкциям по установке, приведенным выше.


🛠 Разработка

Настройка

# Установка с dev зависимостями
poetry install --with dev
# Установка pre-commit хуков
pre-commit install

Доступные Make команды

make run-crawl # Запуск краулера
make run-search QUERY=... # Поиск документов
make run-stats # Статистика БД
make run-generate-samples # Генерация тестовых файлов
make up # Запуск Docker контейнера
make down # Остановка Docker
make lint # Запуск ruff и mypy
make format # Форматирование кода
make clean # Очистка кеша

Качество кода

  • Ruff: Быстрый линтер Python (заменяет flake8, isort)
  • mypy: Строгая проверка типов с --strict
  • pre-commit: Автоматические проверки перед коммитами
  • pytest: Набор тестов с покрытием

Docker

# Сборка и запуск
docker-compose up
# Запуск с произвольной командой
docker-compose run --rm crawler python run_crawler.py search "запрос"# Пересборка
docker-compose build --no-cache

📝 Лицензия

MIT License - свободно используйте и модифицируйте.


About

🔍📄🗂️ A production-ready document crawler with full-text search capabilities. Recursively scans directories, extracts text from various document formats (PDF, DOCX, XLSX, TXT, and more), handles nested archives (ZIP, RAR, 7z), and provides powerful full-text search via SQLite FTS5. Built with clean architecture and type safety.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages