Skip to main content

A robust, extensible web crawler for downloading media content

Project description

Media Crawler

A robust, extensible web crawler for downloading media content from YouTube, SoundCloud, and other platforms. Built with modern Python design patterns and best practices.

๐Ÿ“‹ Table of Contents

โœจ Features

  • ๐ŸŽต Multi-Platform Support: YouTube, SoundCloud, and easily extensible to other platforms
  • ๐Ÿ”„ Smart Crawling: Depth-based crawling with configurable parameters
  • โšก Parallel Downloads: Multi-threaded download manager for fast processing
  • ๐Ÿ’พ State Management: Resume interrupted crawls seamlessly
  • ๐Ÿ—„๏ธ Database Tracking: SQLite-based tracking to avoid duplicate downloads
  • ๐ŸŽจ Beautiful CLI: Rich progress indicators and status updates
  • ๐Ÿ—๏ธ SOLID Design: Clean architecture with dependency injection
  • ๐Ÿ›ก๏ธ Robust Error Handling: Automatic retries with exponential backoff
  • โš™๏ธ Highly Configurable: Extensive configuration options for all components

๐Ÿ“ฆ Installation

Prerequisites

  • Python 3.8 or higher
  • Chrome/Chromium browser
  • ChromeDriver (or use webdriver-manager for automatic installation)
  • FFmpeg (for audio conversion)

Install from source

# Clone the repository
git clone https://github.com/HasanRagab/media-crawler.git
cd media-crawler

# Create a virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Install in development mode
pip install -e .

Install with pip (when published)

pip install media-crawler

๐Ÿš€ Quick Start

Using the Command Line

# Download from YouTube search
python cli.py youtube -k "lofi hip hop" "jazz music" -d 2

# Download from specific YouTube URLs
python cli.py youtube -u "https://youtube.com/@channel" -d 1

# Download from SoundCloud
python cli.py soundcloud -u "https://soundcloud.com/discover" -d 3

Using the Python API

from media_crawler import CrawlerFactory, ApplicationConfig

# Create configuration
config = ApplicationConfig.for_youtube()

# Create crawler
crawler = CrawlerFactory.create_crawler(
    config=config,
    start_urls=["https://www.youtube.com/watch?v=example"]
)

# Start crawling
crawler.crawl()

๐Ÿ“– Usage

Command Line Interface

The CLI provides a simple interface to the crawler functionality:

python cli.py <platform> [options]

Arguments

  • platform: Platform to crawl (youtube or soundcloud)

Options

Input Options (mutually exclusive):

  • -u, --urls URL [URL ...]: Starting URLs to crawl
  • -k, --keywords KEYWORD [KEYWORD ...]: Search keywords (YouTube only)

Crawler Settings:

  • -d, --depth N: Maximum crawl depth (default: 2)
  • -w, --workers N: Number of parallel download workers (default: 8)
  • -s, --scroll N: Number of page scrolls (default: 10)

Download Settings:

  • -o, --output DIR: Output folder for downloads
  • -q, --quality QUALITY: Audio quality/bitrate (default: 192)

Other Options:

  • -v, --verbose: Enable verbose logging
  • --headless/--no-headless: Run browser in headless mode (default: True)
  • --resume: Resume from previous state (default: True)
  • --no-resume: Start fresh, clearing previous state

Examples

# Basic YouTube search with keywords
python cli.py youtube -k "ambient music" -d 2

# Multiple search terms
python cli.py youtube -k "lofi" "jazz" "chill" -d 3

# Crawl specific YouTube channels
python cli.py youtube -u "https://youtube.com/@channel1" "https://youtube.com/@channel2"

# SoundCloud with custom output directory
python cli.py soundcloud -u "https://soundcloud.com/discover" -o ~/Music/SoundCloud/

# High quality downloads with more workers
python cli.py youtube -k "classical music" -q 320 -w 16

# Verbose mode for debugging
python cli.py youtube -k "music" -d 1 -v

# Non-headless mode to see browser
python cli.py youtube -u "https://youtube.com/example" --no-headless

# Start fresh without resuming
python cli.py youtube -k "music" --no-resume

Python API

For more control, use the Python API directly:

Basic Usage

from media_crawler import (
    ApplicationConfig,
    CrawlerFactory,
    CrawlerConfig,
    DownloadConfig
)

# Create configuration
config = ApplicationConfig.for_youtube(
    crawler_config=CrawlerConfig(
        max_depth=2,
        max_workers=8,
        scroll_count=10
    ),
    download_config=DownloadConfig(
        download_folder="~/Music/YouTube/",
        audio_quality="320"
    )
)

# Create and run crawler
crawler = CrawlerFactory.create_crawler(
    config=config,
    start_urls=["https://www.youtube.com/watch?v=example"]
)

crawler.crawl()

Advanced Configuration

from media_crawler import (
    ApplicationConfig,
    CrawlerConfig,
    DatabaseConfig,
    DownloadConfig,
    SeleniumConfig,
    PlatformConfig
)

# Custom platform configuration
platform = PlatformConfig(
    name="CustomPlatform",
    base_domain="example.com",
    base_url="https://example.com",
    ignore_words=["login", "signup", "privacy"]
)

# Detailed configurations
crawler_config = CrawlerConfig(
    max_depth=3,
    max_workers=16,
    scroll_count=20,
    scroll_pause=0.5,
    max_retries=5,
    retry_backoff_base=2
)

database_config = DatabaseConfig(
    db_path="data/custom.db",
    check_same_thread=False
)

download_config = DownloadConfig(
    download_folder="~/Downloads/Media/",
    format="bestaudio/best",
    audio_format="mp3",
    audio_quality="320",
    quiet=False
)

selenium_config = SeleniumConfig(
    headless=True,
    disable_gpu=True,
    no_sandbox=True
)

# Create application config
config = ApplicationConfig(
    platform_config=platform,
    crawler_config=crawler_config,
    database_config=database_config,
    download_config=download_config,
    selenium_config=selenium_config
)

# Create and run crawler
from media_crawler import CrawlerFactory

crawler = CrawlerFactory.create_crawler(
    config=config,
    start_urls=["https://example.com/start"]
)

crawler.crawl()

Error Handling

from media_crawler import (
    CrawlerFactory,
    ApplicationConfig,
    CrawlerException,
    DatabaseException,
    DownloadException
)

try:
    config = ApplicationConfig.for_youtube()
    crawler = CrawlerFactory.create_crawler(
        config=config,
        start_urls=["https://www.youtube.com/watch?v=example"]
    )
    crawler.crawl()
except DatabaseException as e:
    print(f"Database error: {e}")
except DownloadException as e:
    print(f"Download error: {e}")
except CrawlerException as e:
    print(f"Crawler error: {e}")
except KeyboardInterrupt:
    print("Crawl interrupted by user")

โš™๏ธ Configuration

Configuration Classes

The crawler uses a hierarchical configuration system:

CrawlerConfig

Controls crawler behavior:

  • max_depth: Maximum crawl depth (default: 2)
  • max_workers: Number of parallel workers (default: 8)
  • scroll_count: Number of page scrolls (default: 10)
  • scroll_pause: Pause between scrolls in seconds (default: 0.5)
  • max_retries: Maximum retry attempts (default: 3)
  • retry_backoff_base: Exponential backoff base (default: 2)

DatabaseConfig

Database settings:

  • db_path: Path to SQLite database (default: "crawler.db")
  • check_same_thread: SQLite thread safety (default: False)

DownloadConfig

Download settings:

  • download_folder: Output directory (default: "~/Music/Downloads/")
  • format: Video/audio format (default: "bestaudio/best")
  • audio_format: Audio codec (default: "mp3")
  • audio_quality: Bitrate (default: "192")
  • quiet: Suppress yt-dlp output (default: True)
  • user_agent: HTTP user agent string

SeleniumConfig

Browser automation settings:

  • headless: Run browser in headless mode (default: True)
  • disable_gpu: Disable GPU acceleration (default: True)
  • no_sandbox: Disable Chrome sandbox (default: True)
  • disable_dev_shm_usage: Disable /dev/shm usage (default: True)
  • log_level: Chrome log level (default: 3)

PlatformConfig

Platform-specific settings:

  • name: Platform name
  • base_domain: Domain for URL validation
  • base_url: Base URL for relative links
  • ignore_words: Words to filter out from URLs

Environment Variables

You can override default settings using environment variables:

export MEDIA_CRAWLER_DOWNLOAD_FOLDER="~/Music/Downloads/"
export MEDIA_CRAWLER_MAX_DEPTH=3
export MEDIA_CRAWLER_MAX_WORKERS=16
export MEDIA_CRAWLER_HEADLESS=true

๐Ÿ—๏ธ Architecture

The project follows SOLID principles and uses several design patterns:

Design Patterns

  1. Factory Pattern: CrawlerFactory creates fully configured crawler instances
  2. Strategy Pattern: Different download and link extraction strategies
  3. Dependency Injection: Components are injected rather than created internally
  4. Interface Segregation: Abstract base classes define clear contracts

Core Components

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   CrawlerFactory โ”‚  โ† Entry point, creates all components
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ”œโ”€โ”€โ†’ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚    โ”‚ Crawler  โ”‚  โ† Main orchestrator
         โ”‚    โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚         โ”‚
         โ”‚         โ”œโ”€โ”€โ†’ Database (IDatabase)
         โ”‚         โ”œโ”€โ”€โ†’ WebDriver (IWebDriver)
         โ”‚         โ”œโ”€โ”€โ†’ DownloadManager
         โ”‚         โ”œโ”€โ”€โ†’ LinkExtractor (ILinkExtractor)
         โ”‚         โ”œโ”€โ”€โ†’ StateManager
         โ”‚         โ””โ”€โ”€โ†’ ProgressDisplay
         โ”‚
         โ””โ”€โ”€โ†’ ApplicationConfig
              โ”œโ”€โ”€ CrawlerConfig
              โ”œโ”€โ”€ DatabaseConfig
              โ”œโ”€โ”€ DownloadConfig
              โ”œโ”€โ”€ SeleniumConfig
              โ””โ”€โ”€ PlatformConfig

Component Details

  • Crawler: Main orchestration logic, manages crawl loop
  • Database: Tracks downloaded content, prevents duplicates
  • WebDriver: Handles page loading and JavaScript rendering
  • DownloadManager: Parallel download execution with retry logic
  • LinkExtractor: Platform-specific link extraction strategies
  • StateManager: Saves/loads crawler state for resumption
  • ProgressDisplay: Real-time progress updates

See ARCHITECTURE.md for detailed architecture documentation.

๐Ÿ“ Project Structure

media-crawler/
โ”œโ”€โ”€ cli.py                      # Command-line interface
โ”œโ”€โ”€ setup.py                    # Package setup
โ”œโ”€โ”€ pyproject.toml             # Project metadata
โ”œโ”€โ”€ requirements.txt           # Dependencies
โ”œโ”€โ”€ Makefile                   # Build and test automation
โ”œโ”€โ”€ LICENSE                    # MIT License
โ”‚
โ”œโ”€โ”€ media_crawler/             # Main package
โ”‚   โ”œโ”€โ”€ __init__.py           # Package exports
โ”‚   โ”œโ”€โ”€ config.py             # Configuration classes
โ”‚   โ”œโ”€โ”€ crawler.py            # Main crawler logic
โ”‚   โ”œโ”€โ”€ factory.py            # Factory for creating crawlers
โ”‚   โ”œโ”€โ”€ database.py           # Database interface & implementation
โ”‚   โ”œโ”€โ”€ webdriver.py          # Selenium WebDriver wrapper
โ”‚   โ”œโ”€โ”€ downloader.py         # Download manager & strategies
โ”‚   โ”œโ”€โ”€ link_extractor.py     # Link extraction strategies
โ”‚   โ”œโ”€โ”€ state_manager.py      # State persistence
โ”‚   โ”œโ”€โ”€ progress.py           # Progress display
โ”‚   โ”œโ”€โ”€ utils.py              # Utility functions
โ”‚   โ””โ”€โ”€ exceptions.py         # Custom exceptions
โ”‚
โ”œโ”€โ”€ tests/                     # Unit tests
โ”‚   โ”œโ”€โ”€ test_config.py
โ”‚   โ”œโ”€โ”€ test_crawler.py
โ”‚   โ”œโ”€โ”€ test_database.py
โ”‚   โ””โ”€โ”€ ...
โ”‚
โ”œโ”€โ”€ examples/                  # Example scripts
โ”‚   โ”œโ”€โ”€ main.py               # Basic usage example
โ”‚   โ”œโ”€โ”€ examples.py           # Various usage examples
โ”‚   โ””โ”€โ”€ diagnose.py           # Diagnostic script
โ”‚
โ”œโ”€โ”€ docs/                      # Documentation
โ”‚   โ”œโ”€โ”€ ARCHITECTURE.md       # Architecture details
โ”‚   โ””โ”€โ”€ API.md                # API documentation
โ”‚
โ””โ”€โ”€ scripts/                   # Utility scripts
    โ”œโ”€โ”€ QUICKSTART.py
    โ”œโ”€โ”€ PROJECT_OVERVIEW.py
    โ””โ”€โ”€ ORGANIZATION_SUMMARY.py

๐Ÿ”ง Development

Setup Development Environment

# Clone repository
git clone https://github.com/HasanRagab/media-crawler.git
cd media-crawler

# Create virtual environment
python -m venv .venv
source .venv/bin/activate

# Install development dependencies
pip install -r requirements.txt
pip install -e ".[dev]"

Code Style

The project uses:

  • black for code formatting
  • flake8 for linting
  • mypy for type checking
# Format code
make format

# Run linters
make lint

# Type checking
make typecheck

Project Commands (Makefile)

make help          # Show available commands
make install       # Install package and dependencies
make dev-install   # Install with development dependencies
make format        # Format code with black
make lint          # Run flake8 linter
make typecheck     # Run mypy type checker
make test          # Run tests
make test-coverage # Run tests with coverage report
make clean         # Clean build artifacts
make build         # Build distribution packages

๐Ÿงช Testing

Run Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=media_crawler --cov-report=html

# Run specific test file
pytest tests/test_crawler.py

# Run with verbose output
pytest -v

Write Tests

Tests are organized by module:

# tests/test_crawler.py
import pytest
from media_crawler import Crawler, ApplicationConfig

def test_crawler_initialization():
    config = ApplicationConfig.for_youtube()
    # ... test code

๐Ÿค Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Make your changes
  4. Write tests for new functionality
  5. Ensure tests pass: pytest
  6. Format code: make format
  7. Commit changes: git commit -am 'Add new feature'
  8. Push to branch: git push origin feature/your-feature
  9. Submit pull request

Code Guidelines

  • Follow PEP 8 style guide
  • Write docstrings for all public methods
  • Add type hints
  • Keep functions focused and small
  • Write unit tests for new features
  • Update documentation

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

๐Ÿ“ž Support

๐Ÿ—บ๏ธ Roadmap

  • Add support for more platforms (Spotify, Apple Music)
  • Implement GUI interface
  • Add playlist management
  • Support for video downloads
  • Docker containerization
  • Cloud storage integration
  • REST API interface
  • Real-time monitoring dashboard

Made with โค๏ธ by Hasan Ragab

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymedia_crawler-1.0.3.tar.gz (60.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymedia_crawler-1.0.3-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file pymedia_crawler-1.0.3.tar.gz.

File metadata

  • Download URL: pymedia_crawler-1.0.3.tar.gz
  • Upload date:
  • Size: 60.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pymedia_crawler-1.0.3.tar.gz
Algorithm Hash digest
SHA256 6060ca862a52f04fec5db6df38764ba5162414cb1d7c9b7db37c945d8b65aa64
MD5 c14b70982e7ffc9b01de5f3b7f5a11b1
BLAKE2b-256 9ec84332b204b6ca23036df2573cd2b15faab263cfaa850397cf7b23ee9b4e7a

See more details on using hashes here.

File details

Details for the file pymedia_crawler-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for pymedia_crawler-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c6f7c3b9b32f12b465e567d018116cbb1489ba6898d8ba291e40a1185fc561a0
MD5 f64872ce39be373994415295a03cda38
BLAKE2b-256 e2fb5b66e9f33ce72fb3729740daa3e71e745c3f08cec045f0488d6a37d9b9db

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page