Optimized fork with improved naming conventions, duplicate file prevention, sequential file numbering, username detection, and performance enhancements.
This is an enhanced fork of the original Erome Downloader with significant improvements to organization, performance, and user experience.
✨ Enhanced Folder Naming: Album Name (ID) [Username] instead of Album Name (ID)
📁 Duplicate Download Prevention: Uses individual media IDs to proceed or skip files
📝 Sequential File Naming: Album (001).mp4 instead of random media IDs
👤 Username Detection: Automatically extracts uploader names
⚡ Performance Optimizations: Faster downloads with optimized chunk sizes
🎨 Smart Truncation: Intelligently handles long names while preserving critical info
📊 Order Preservation: Files maintain their original album sequence
Before (Original):
Downloads/
└── Wet T-Shirt Clip (MgPP9itp)/
├── qZABBB4g_720p.mp4
├── xCDEFF9h_1080p.mp4
└── yGHIJK2i_480p.jpg
After (Enhanced):
Downloads/
└── Wet T-Shirt Clip (MgPP9itp) [Red5]/
├── Wet T-Shirt Clip (001).mp4
├── Wet T-Shirt Clip (002).mp4
└── Wet T-Shirt Clip (003).jpg
- Python 3.10 or higher
- pip (Python package installer)
-
Clone the repository
git clone https://github.com/TheGitGooner/EromeDownloader-EDL.git cd EromeDownloader-EDL -
Install dependencies
pip install -r requirements.txt
Extract all album URLs from a user's profile:
python main.py -p https://www.erome.com/usernamealbum URL's will be compiled into profile_dump.txt
Add album URLs to URLs.txt (one per line):
https://www.erome.com/a/ABC123
https://www.erome.com/a/DEF456
Then run:
python main.pySpecify a custom download location:
python main.py --custom-path /path/to/downloads# Add URL to URLs.txt
https://www.erome.com/a/ABC123
# Run downloader
python main.pyResult:
Downloads/
└── Vacation Photos (ABC123) [JohnDoe]/
├── Vacation Photos (01).jpg
├── Vacation Photos (02).jpg
├── Vacation Photos (03).mp4
...
URLs.txt:
https://www.erome.com/a/ABC123
https://www.erome.com/a/DEF456
https://www.erome.com/a/GHI789
Run:
python main.pyResult:
Downloads/
├── Vacation Photos (ABC123) [JohnDoe]/
├── Beach Trip (DEF456) [BeachLover]/
└── Mountain Hike (GHI789) [Hiker123]/
# Short name - keeps everything
"Summer Vacation (abc123) [TravelGirl]"
# Medium name - truncates album title
"My Amazing Summer Vacation Phot... (abc123) [TravelGirl]"
# Long name - prioritizes ID and username
"(abc123) [TravelGirl]"# Short album name - no truncation
"Vacation (001).jpg"
"Vacation (002).mp4"
# Long album name - truncates album, keeps number
"My Amazing Summer Vacation... (001).jpg"
"My Amazing Summer Vacation... (002).mp4"
# Very long - number always preserved
"(001).jpg"
"(002).mp4"- Async downloads (aiohttp)
- Optional asynchronous downloader using aiohttp
- Significantly improves throughput on high-latency connections
- Resume support for partial files
- Uses HTTP Range headers
- Prevents restarting large downloads
- Retry logic with exponential backoff
- Configurable MAX_RETRIES
- Exponential backoff (RETRY_BACKOFF_BASE)
- Shared HTTP session reuse
- Reduces connection overhead
- Improves download efficiency
- Faster session reuse
- Centralized timeout configuration
- CONNECT_TIMEOUT
- READ_TIMEOUT
- Consistent headers
- User-Agent
- Referer
- Origin
- Proper cookie/session handling for media requests
- Better configurable performance tuning in config.py
- USE_ASYNC_DOWNLOADER
- MAX_RETRIES
- RETRY_BACKOFF_BASE
- Timeout settings
- Worker tuning options
- Better configurable performance tuning
- Increased download speed
- Improved bandwidth utilization
- Resource efficiency
- Increased parallelism controls
- Configurable MAX_WORKERS
- Better chunk size handling for different file sizes
- Username detection
- Enhanced folder naming
- Album order preservation
- Duplicate file URL detection
- Enhanced file naming
- Protection against long path issues
- Documentation & explanation improvements
- Code quality improvements
Implementation: downloader.py - extract_and_format_album_title()
Changes:
- Added
extract_profile_name()function with 4 fallback methods - Modified folder format from
Album (ID)toAlbum (ID) [Username] - Implemented smart truncation that prioritizes album ID and username
Username Detection Methods:
- Primary:
<a id="user_name">element - Fallback 1:
<a class="user">element - Fallback 2:
<meta name="author">tag - Fallback 3: Parse from page title pattern
Smart Truncation Logic:
# Full name fits → use it
"Album Name (ID123) [Username]"
# Name too long → truncate album name
"Very Long Album Name That... (ID123) [Username]"
# Extremely long → prioritize ID and username
"(ID123) [Username]"Implementation: downloader.py - generate_sequential_filename()
Changes:
- Added
get_album_name_for_files()to extract clean album name - Modified
extract_download_links()to preserve order (changed fromsetto ordered list) - Implemented
generate_sequential_filename()for consistent naming - Updated
download_item()to accept file position parameters
Automatic Padding:
- 1-9 files:
(1),(2),(3) - 10-99 files:
(01),(02), ...,(99) - 100-999 files:
(001),(002), ...,(999) - Automatically adjusts based on total file count!
Example:
Album with 150 files:
├── Album Name (001).jpg
├── Album Name (002).mp4
...
└── Album Name (150).mp4
Implementation: downloader.py - extract_download_links()
Original Approach:
# Used set comprehension - loses order
return list({*image_download_links, *video_download_links})Enhanced Approach:
# Maintains order with duplicate checking
download_links = []
seen = set()
for image in images:
if url not in seen:
download_links.append(url)
seen.add(url)
for video in videos:
if url not in seen:
download_links.append(url)
seen.add(url)Result: Files are numbered in the exact order they appear in the album.
Implementation: config.py
| Setting | Original | Enhanced | Improvement |
|---|---|---|---|
MAX_WORKERS |
2 | 16 | 8x more concurrent downloads |
LARGE_FILE_CHUNK_SIZE |
16 KB | 1 MB | 64x larger chunks |
THRESHOLDS[0] |
2 KB | 64 KB | 32x larger |
THRESHOLDS[1] |
4 KB | 128 KB | 32x larger |
THRESHOLDS[2] |
8 KB | 256 KB | 32x larger |
CONNECT_TIMEOUT |
- | 10s | Added explicit timeout |
READ_TIMEOUT |
20s | 30s | 50% longer |
Performance Impact:
- 2-3x faster downloads on high-bandwidth connections (>50 Mbps)
- 1.5-2x faster on moderate connections (10-50 Mbps)
- More efficient use of system resources
Implementation: download_utils.py
Purpose: Execute downloads in parallel while maintaining sequential file numbering.
Key Features:
- Passes
file_numberandtotal_filesto each download task - Maintains original
run_in_parallel()for backwards compatibility - Enables sequential naming without sacrificing parallel download speed
def run_in_parallel_ordered(
func: callable,
items: list,
live_manager: LiveManager,
identifier: str,
*args: tuple,
) -> None:
"""Execute in parallel with sequential numbering."""
for current_task, item in enumerate(items):
file_number = current_task + 1 # 1-indexed
future = executor.submit(
func, item, task_id, live_manager,
*args, file_number, len(items)
)Implementation: config.py
New Constants:
CONNECT_TIMEOUT = 10 # Connection establishment timeout
READ_TIMEOUT = 30 # Data read timeout
MAX_FILENAME_LENGTH = 200 # Maximum filename/folder lengthOptimized Settings:
# CPU-aware worker count
CPU_CORES = os.cpu_count() or 4
MAX_WORKERS = min(16, CPU_CORES * 2) # I/O bound optimization
# Improved chunk sizing
LARGE_FILE_CHUNK_SIZE = 1 * MB # Up from 16 KBerome-downloader-enhanced/
├── downloader.py # Enhanced with username detection & sequential naming
├── main.py # Main entry point (unchanged)
├── URLs.txt # Input file for album URLs
├── requirements.txt # Python dependencies
└── src/
├── config.py # Optimized performance settings
├── download_utils.py # Added run_in_parallel_ordered()
├── erome_utils.py # URL validation (unchanged)
├── file_utils.py # File operations (unchanged)
├── general_utils.py # Utility functions (unchanged)
├── profile_crawler.py # Profile scraping (unchanged)
└── managers/
├── live_manager.py # Live UI updates
├── log_manager.py # Logging
└── progress_manager.py # Progress tracking
| File | Changes | Lines Modified |
|---|---|---|
downloader.py |
Major enhancements | ~150+ lines added |
config.py |
Performance optimizations | ~20 lines modified |
download_utils.py |
New parallel function | ~50 lines added |
main.py- Entry pointerome_utils.py- URL validationfile_utils.py- File operationsgeneral_utils.py- Utility functionsprofile_crawler.py- Profile scraping- All manager modules
- Album: 15 files (mix of images and videos)
- Connection: 100 Mbps
- System: Windows 10, i7 processor
| Version | Download Time | Improvement |
|---|---|---|
| Original | 1m 47s | Baseline |
| Enhanced | 1m 38s | 8% faster ✓ |
Faster with enhancements:
- ✓ Larger chunk sizes reduce I/O overhead
- ✓ More concurrent workers utilize bandwidth better
- ✓ Optimized timeouts reduce wait times
Maintained performance:
- Sequential numbering adds negligible overhead
- Username detection happens once per album
- Order preservation doesn't impact download speed
- Albums with identical names may overwrite each other
- Large albums (1000+ files) may take significant time
- Network interruptions require manual restart
- Username detection fails gracefully to "Unknown" if not found
- Sequential numbering assumes files appear in correct order on page
- Longer folder names may cause issues on filesystems with path length limits
Contributions are welcome and feature requests!
- Create GUI interface
- Add download queue management
- Create download scheduler
- Add cloud storage integration
- Anything you feel would greatly improve archiving capabilities
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
- Original Author: Lysagxra - For creating the base downloader
- Libraries Used:
- BeautifulSoup4 - HTML parsing
- Requests - HTTP library
- Rich - Terminal UI
- aiohttp - Async HTTP (optional)
- Original Project: Erome Downloader Issues
- This Fork: Create an Issue
This tool is intended for personal use only. Please respect:
- Copyright laws
- Terms of service
- Content creators' rights
- Personal privacy
Use responsibly and ethically.