No description
Find a file
2025-08-24 23:08:46 -05:00
.dockerignore Se agrego dockerfile 2025-08-24 23:08:46 -05:00
.env Se mejoro carga de imagenes y rate limit 2025-08-24 22:20:46 -05:00
.gitignore TMOHentai API 2025-08-24 04:30:27 -05:00
app.py Se mejoro carga de imagenes y rate limit 2025-08-24 22:20:46 -05:00
Dockerfile Se agrego dockerfile 2025-08-24 23:08:46 -05:00
README.md Se mejoro carga de imagenes y rate limit 2025-08-24 22:20:46 -05:00
requirements.txt TMOHentai API 2025-08-24 04:30:27 -05:00
scraper.py Se mejoro carga de imagenes y rate limit 2025-08-24 22:20:46 -05:00

🚀 TMOHentai Scraper API v1.3.0

Python Flask License Status

Una API REST moderna y altamente optimizada para hacer scraping del sitio TMOHentai, con arquitectura escalable, rate limiting inteligente y múltiples estrategias de optimización de rendimiento.

📋 Tabla de Contenidos

🎯 Características

Core Features

  • 🔍 Búsqueda Avanzada: Por nombre, artista, revista, tag con filtros múltiples
  • Lazy Loading: Búsqueda básica ultra-rápida + detalles bajo demanda
  • 🖼️ Proxy de Imágenes: Bypass inteligente de protecciones anti-hotlink
  • 📊 Extracción Detallada: Tags, géneros, artistas, páginas, idiomas
  • 🗂️ Navegación por Secciones: Hentai, Yaoi, Yuri con paginación

🚀 Optimizaciones de Rendimiento

  • 💾 Cache Inteligente: Sistema LRU con TTL de 5 minutos
  • 🔄 Threading Paralelo: Procesamiento concurrente de detalles
  • ⏱️ Rate Limiting Adaptativo: Diferentes límites por endpoint
  • 🎯 Validaciones Robustas: Sanitización y validación de inputs
  • 📝 Logging Estructurado: Monitoreo y debugging avanzado

🛡️ Seguridad y Estabilidad

  • 🔒 Rate Limiting por IP: Prevención de abuso
  • 🧹 Input Sanitization: Protección contra XSS e inyecciones
  • 🌐 CORS Configurado: Integración segura con frontend
  • Timeouts Configurables: Prevención de requests colgados
  • 🔐 Validación de URLs: Solo dominios permitidos

🏗️ Arquitectura

📁 Estructura del Proyecto

searchtmoh/
├── app.py              # 🚀 API Flask principal (674 líneas)
├── scraper.py          # 🔍 Motor de scraping (635 líneas)
├── requirements.txt    # 📦 Dependencias del proyecto
├── .env               # ⚙️ Variables de configuración
├── .gitignore         # 🙈 Archivos ignorados
└── README.md          # 📚 Esta documentación

🔧 Stack Tecnológico

  • Framework: Flask 3.0.0 (moderno y ligero)
  • Web Scraping: BeautifulSoup4 + requests + lxml
  • Concurrencia: ThreadPoolExecutor (máx 3 workers)
  • Cache: In-memory LRU con TTL automático
  • CORS: Flask-CORS para integración frontend
  • Environment: python-dotenv para configuración
  • Logging: Python logging con formato estructurado

📊 Flujo de Datos

Frontend → Flask API → Rate Limiting → Validation → TMOHentaiScraper → Cache → BeautifulSoup → Target Site
    ↑                                                                                                    ↓
    ← JSON Response ← Data Processing ← Content Extraction ← HTML Parsing ← HTTP Response ←

Instalación

📋 Prerequisitos

  • Python 3.8+
  • pip (Python package manager)
  • Conexión a internet estable

🔧 Instalación Paso a Paso

# 1. Clonar el repositorio
git clone https://git.lokius.me/xlokius/tmohentai_api.git
cd Search-TMOH/tmohentai_api

# 2. Crear entorno virtual (recomendado)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# o
venv\\Scripts\\activate  # Windows

# 3. Instalar dependencias
pip install -r requirements.txt

# 4. Configurar variables de entorno
cp .env.example .env  # Si es necesario
nano .env  # Editar configuración

# 5. Ejecutar la aplicación
python app.py

🐳 Docker (Opcional)

# Crear imagen Docker
docker build -t tmohentai-api .

# Ejecutar contenedor
docker run -p 3000:3000 tmohentai-api

🔧 Configuración

📝 Variables de Entorno (.env)

# Servidor
DEBUG=True                          # Modo debug
PORT=3000                          # Puerto del servidor
HOST=127.0.0.1                    # Host del servidor

# Scraper Configuration
REQUEST_TIMEOUT=10                 # Timeout de requests (segundos)
MAX_RETRIES=3                      # Máximo reintentos

# Cache y Rendimiento
CACHE_TTL=300                      # TTL del cache (segundos)
MAX_CACHE_SIZE=100                 # Máximo entradas en cache
MIN_REQUEST_INTERVAL=0.3           # Intervalo mínimo entre requests

# Rate Limiting (requests per minute)
MAX_SEARCH_REQUESTS=5              # Búsqueda completa
MAX_SEARCH_BASIC_REQUESTS=100      # Búsqueda básica
MAX_CONTENT_REQUESTS=20            # Contenido por página
MAX_DETAILS_REQUESTS=200           # Detalles específicos
MAX_PROXY_REQUESTS=200             # Proxy de imágenes (4 imgs/1.2s)
RATE_LIMIT_WINDOW=60              # Ventana de tiempo (segundos)

# Threading
MAX_WORKERS=3                      # Máximo workers concurrentes
THREAD_TIMEOUT=30                  # Timeout por thread

# Validaciones
MAX_QUERY_LENGTH=200               # Longitud máxima de query
MAX_PAGE_NUMBER=1000               # Número máximo de página
MAX_DETAILS_LIMIT=24               # Máximo detalles por búsqueda

⚙️ Configuración Avanzada

# Configuración adicional en app.py
app.config['JSON_SORT_KEYS'] = False
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True

# Logging personalizado
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

📡 Endpoints

🏠 Información General

GET /

Información general de la API y documentación

GET http://localhost:3000/

Response:

{
  "api_name": "TMOHentai Scraper API",
  "version": "1.3.0",
  "status": "active",
  "endpoints": { ... },
  "search_parameters": { ... },
  "performance_features": [ ... ]
}

GET /api/health

Health check y estado del sistema

GET http://localhost:3000/api/health

Response:

{
  "status": "healthy",
  "message": "API y sitio objetivo funcionando correctamente",
  "timestamp": 1703094123.456,
  "cache_size": 15,
  "version": "1.3.0"
}

🔍 Búsqueda

GET /api/search-basic

Búsqueda básica ultra-rápida (2-3 segundos)

Parámetro Tipo Requerido Default Descripción
query string - Texto a buscar (2-200 chars)
search_by enum name name, artist, tag
page integer 1 Número de página (1-1000)
view enum thumbnails list, thumbnails
order enum publication_date publication_date, rating, title, views
order_dir enum asc asc, desc
type enum all all, hentai, yaoi, yuri

Rate Limit: 100 requests/minuto

GET http://localhost:3000/api/search-basic?query=naruto&search_by=name&page=1

Response:

{
  "success": true,
  "query": "naruto",
  "search_by": "name",
  "basic_mode": true,
  "details_extracted": false,
  "content": [
    {
      "id": "12345",
      "title": "Naruto - Love Stories",
      "image_url": "https://imgrojo.tmohentai.com/...",
      "url": "https://tmohentai.com/reader/naruto-love-stories",
      "rating": 8.5,
      "type": "hentai",
      "basic_info_only": true
    }
  ],
  "pagination": {
    "has_next": true,
    "has_previous": false,
    "next_page": 2
  },
  "total_results": 24
}

Búsqueda completa con detalles (8-15 segundos)

Mismos parámetros que /api/search-basic + max_details:

Parámetro Tipo Requerido Default Descripción
max_details integer 10 Máximo detalles a extraer (1-24)

Rate Limit: 5 requests/minuto

GET http://localhost:3000/api/search?query=love&search_by=artist&max_details=5

Response:

{
  "success": true,
  "query": "love",
  "search_by": "artist",
  "detailed_extraction": true,
  "details_processed": 5,
  "content": [
    {
      "id": "12345",
      "title": "Love Collection",
      "rating": 8.7,
      "image_url": "https://imgrojo.tmohentai.com/...",
      "information": {
        "artists": ["Artist Name"],
        "magazines": ["Weekly Jump"],
        "genders": ["Romance", "Comedy"],
        "tags": ["love", "romance", "school"],
        "language_code": "es",
        "pages": 25,
        "detailed_rating": 8.7
      }
    }
  ]
}

📊 Detalles Específicos

GET /api/details

Obtener detalles de un contenido específico

Parámetro Tipo Requerido Descripción
url string URL completa del contenido tmohentai.com

Rate Limit: 200 requests/minuto

GET http://localhost:3000/api/details?url=https://tmohentai.com/reader/example

Response:

{
  "success": true,
  "url": "https://tmohentai.com/reader/example",
  "details": {
    "artists": ["Artist Name", "Co-Artist"],
    "magazines": ["Weekly Jump"],
    "genders": ["Romance", "Comedy", "School"],
    "tags": ["love", "school", "romance"],
    "uploaded_by": ["UserUploader"],
    "language_code": "es",
    "language_name": "Español",
    "pages": 25,
    "detailed_rating": 8.7,
    "full_title": "Complete Title",
    "publication_date": "2024-01-15"
  }
}

📄 Contenido

GET /api/content

Obtener contenido de la página principal

Parámetro Tipo Requerido Default Descripción
page integer 1 Número de página (1-1000)

Rate Limit: 20 requests/minuto

GET http://localhost:3000/api/content?page=2

GET /api/sections/<section>

Obtener contenido por sección

Parámetro Tipo Requerido Valores Descripción
section string hentai, yaoi, yuri Sección a consultar
page integer 1 Número de página

Rate Limit: 15 requests/minuto

GET http://localhost:3000/api/sections/hentai?page=1

🖼️ Proxy de Imágenes

GET /api/proxy-image

Proxy para imágenes con bypass anti-hotlink

Parámetro Tipo Requerido Descripción
url string URL de imagen de *.tmohentai.com

Rate Limit: 200 requests/minuto (4 imágenes cada 1.2s)

GET http://localhost:3000/api/proxy-image?url=https://imgrojo.tmohentai.com/path/image.jpg

Características:

  • Bypass inteligente de protecciones anti-hotlink
  • 🛡️ Solo dominios *.tmohentai.com permitidos
  • 🎭 User-Agent spoofing y headers completos
  • 🔄 Retry automático con session warming
  • Streaming de contenido en chunks de 8KB

🔧 Utilidades

GET /api/filters

Obtener filtros disponibles para búsquedas

GET http://localhost:3000/api/filters

Response:

{
  "success": true,
  "filters": {
    "search_by": ["name", "artist", "magazine", "tag"],
    "view": ["list", "thumbnails"],
    "order": ["publication_date", "rating", "title", "views"],
    "order_dir": ["asc", "desc"],
    "type": ["all", "hentai", "yaoi", "yuri"]
  }
}

📊 Ejemplos de Uso

🚀 Caso de Uso 1: Búsqueda Rápida

# 1. Búsqueda básica inicial (2-3s)
curl "http://localhost:3000/api/search-basic?query=naruto&page=1"

# 2. Navegar páginas (instantáneo)
curl "http://localhost:3000/api/search-basic?query=naruto&page=2"

# 3. Obtener detalles específicos (1-2s)
curl "http://localhost:3000/api/details?url=https://tmohentai.com/reader/example"

🔍 Caso de Uso 2: Búsqueda Detallada

# Búsqueda completa con todos los detalles (8-12s)
curl "http://localhost:3000/api/search?query=romance&search_by=tag&max_details=10&order=rating&order_dir=desc"

📄 Caso de Uso 3: Exploración por Secciones

# Explorar sección específica
curl "http://localhost:3000/api/sections/yuri?page=1"

# Contenido de la página principal
curl "http://localhost:3000/api/content?page=1"

🖼️ Caso de Uso 4: Manejo de Imágenes

# Proxy de imagen con bypass anti-hotlink
curl "http://localhost:3000/api/proxy-image?url=https://imgrojo.tmohentai.com/uploads/mini/example.jpg" -o image.jpg

🧪 Testing con Python

import requests

# Cliente API básico
class TMOHentaiAPI:
    def __init__(self, base_url="http://localhost:3000"):
        self.base_url = base_url
        
    def search_basic(self, query, **kwargs):
        params = {"query": query, **kwargs}
        return requests.get(f"{self.base_url}/api/search-basic", params=params).json()
        
    def get_details(self, url):
        params = {"url": url}
        return requests.get(f"{self.base_url}/api/details", params=params).json()

# Uso
api = TMOHentaiAPI()
results = api.search_basic("naruto", search_by="name", page=1)
print(f"Encontrados {len(results['content'])} resultados")

🛡️ Seguridad

🔒 Rate Limiting

# Rate limiting por IP con ventana deslizante
@rate_limit(max_requests=100, per_seconds=60)
def search_content_basic():
    # Endpoint protegido

Límites por Endpoint:

  • Búsqueda básica: 100/min
  • Búsqueda completa: 5/min
  • Detalles específicos: 200/min
  • Proxy imágenes: 200/min (4 cada 1.2s)
  • Contenido: 20/min
  • Secciones: 15/min

🧹 Input Sanitization

def sanitize_query(query: str, max_length: int = 200) -> str:
    dangerous_chars = ['<', '>', '"', "'", '&', 'script', 'javascript']
    sanitized = query.strip()
    for char in dangerous_chars:
        sanitized = sanitized.replace(char, '')
    return sanitized[:max_length]

🌐 CORS y Headers

# CORS configurado para integración segura
CORS(app)

# Headers de seguridad en responses
headers = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET',
    'Cache-Control': 'public, max-age=3600'
}

🔐 Validaciones

  • Validación de URLs (solo dominios permitidos)
  • Validación de parámetros (rangos, tipos, longitudes)
  • Verificación de Content-Type para imágenes
  • Sanitización de queries de búsqueda
  • Timeouts configurables para prevenir hanging

Rendimiento

📊 Métricas de Rendimiento

Operación Tiempo Cache Hit Throughput Rate Limit
Búsqueda básica 2-3s 60-70% ~100/min 100/min
Búsqueda completa 8-12s 60-70% ~5/min 5/min
Detalles específicos 1-3s 60-70% ~200/min 200/min
Proxy imagen 0.5-1.5s N/A ~200/min 200/min
Health check <500ms N/A Ilimitado N/A

💾 Sistema de Cache

# Cache LRU con TTL automático
self.cache = {}                    # In-memory storage
self.cache_ttl = 300              # 5 minutos TTL
self.max_cache_size = 100         # Máximo 100 entradas

# Hit rate esperado: 60-70%
# Invalidación: Automática por tiempo

🔄 Threading y Concurrencia

# ThreadPoolExecutor para detalles paralelos
with ThreadPoolExecutor(max_workers=3) as executor:
    futures = [executor.submit(extract_details, url) for url in urls]
    results = [future.result(timeout=30) for future in futures]

⏱️ Optimizaciones de Red

  • Connection Pooling: Reutilización de sesiones HTTP
  • Chunked Transfer: Streaming de imágenes en chunks de 8KB
  • Keep-Alive: Conexiones persistentes
  • Compression: Gzip automático para responses JSON

🧪 Testing

🔧 Unit Tests

# Ejecutar tests unitarios
python -m pytest tests/ -v

# Tests específicos
python -m pytest tests/test_scraper.py -v
python -m pytest tests/test_endpoints.py -v

🚀 Integration Tests

# Test de integración completa
python test_rate_limit.py

# Health check
curl http://localhost:3000/api/health

# Test de carga
ab -n 100 -c 10 http://localhost:3000/api/search-basic?query=test

📊 Performance Tests

# Benchmark de endpoints
python benchmark.py

# Test de memoria
python -m memory_profiler app.py

# Test de concurrencia
python concurrent_test.py

📈 Monitoreo

📝 Logging

# Logging estructurado
logger.info(f"Búsqueda básica: '{query}' por {search_by}, página {page}")
logger.warning(f"Rate limit excedido para IP: {client_ip}")
logger.error(f"Error en endpoint: {str(e)}")

# Archivos de log
tail -f app.log

📊 Métricas

# Health check con métricas
GET /api/health
{
  "status": "healthy",
  "cache_size": 45,
  "timestamp": 1703094123.456,
  "version": "1.3.0"
}

🔍 Debugging

# Debug mode
DEBUG=True python app.py

# Verbose logging
python app.py --log-level DEBUG

# Request tracing
curl -H "X-Debug: true" http://localhost:3000/api/search-basic?query=test

🚨 Troubleshooting

Errores Comunes

Error 429 - Rate Limit Exceeded

{
  "success": false,
  "error": "Demasiadas solicitudes. Intenta de nuevo más tarde."
}

Solución: Esperar 60 segundos o usar endpoint con mayor límite

Error 400 - Bad Request

{
  "success": false,
  "error": "El parámetro query es requerido"
}

Solución: Verificar parámetros requeridos y formatos

Error 502 - Bad Gateway

{
  "success": false,
  "error": "Error de conexión al obtener la imagen"
}

Solución: Verificar conectividad con tmohentai.com

🔧 Soluciones

Cache Issues

# Limpiar cache
curl http://localhost:3000/api/health  # Ver cache_size
# Reiniciar aplicación para limpiar cache

Performance Issues

# Verificar recursos del sistema
htop
df -h

# Optimizar configuración
MIN_REQUEST_INTERVAL=0.5  # Aumentar si es necesario
MAX_WORKERS=2             # Reducir workers

Connectivity Issues

# Test de conectividad
curl -I https://tmohentai.com/

# Verificar DNS
nslookup tmohentai.com

# Test de proxy
curl "http://localhost:3000/api/proxy-image?url=https://tmohentai.com/favicon.ico"

📞 Soporte

Para reportar bugs o solicitar features:

  1. Verificar logs: tail -f app.log
  2. Ejecutar health check: GET /api/health
  3. Reproducir con curl/Postman
  4. Abrir issue con información completa

📄 API Reference Summary

Endpoint Method Rate Limit Purpose
/ GET Información de la API
/api/health GET Health check
/api/filters GET Filtros disponibles
/api/search-basic GET 100/min Búsqueda rápida
/api/search GET 5/min Búsqueda detallada
/api/details GET 200/min Detalles específicos
/api/content GET 20/min Contenido principal
/api/sections/<section> GET 15/min Contenido por sección
/api/proxy-image GET 200/min Proxy de imágenes

🎯 Versión: 1.3.0
🔧 Stack: Flask + BeautifulSoup + requests
Performance: Cache + Threading + Rate Limiting
🛡️ Security: Input sanitization + CORS + Validation

¡API lista para producción con arquitectura escalable y optimizada! 🚀