Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EaseYourIGStats

Python PySide6 Platform Tests Status

Aplicación de escritorio para convertir el export de datos de Instagram — cientos de ficheros JSON que nadie abre a mano — en un dashboard visual: actividad en el tiempo, mensajes, conexiones y limpieza de quién no te sigue de vuelta.

Interfaz Fluent Design (PySide6 + QFluentWidgets) con tema claro/oscuro automático, gráficos nativos y todo el procesamiento pesado corriendo en segundo plano para que la UI nunca se congele.

Empezó como un script de consola de una sola función (NonFollowersChecker: comparar followers_1.html vs following.json). Esa función se conserva intacta — pestaña Limpieza dentro de Conexiones — pero hoy la aplicación analiza y visualiza el export completo, no solo followers/following.

Índice

Por qué este proyecto

Instagram te deja pedir "toda tu información", pero te la entrega como un zip de cientos de ficheros JSON con esquemas inconsistentes entre sí y, en cuentas con años de actividad, gigabytes de datos — nadie los abre a mano. Este proyecto existe para convertir ese export en algo que se puede mirar y entender en un par de minutos, sin subir tus datos a ningún servicio de terceros: todo corre en local.

Además de ser una herramienta que uso yo mismo, es el sitio donde he ido metiendo intencionadamente problemas de ingeniería reales — un fichero de más de 200 MB que hay que parsear sin congelar la UI, una tabla que tiene que renderizar cientos de miles de filas, un formato de texto que Instagram entrega mal codificado — en vez de datos de ejemplo bonitos y pequeños.

Características

  • Resumen (dashboard): conteos totales por categoría, un gráfico de actividad en el tiempo (likes + comentarios + stories + mensajes por mes) y un ranking de las cuentas con las que más interactúas.
  • Actividad: sub-pestañas de Me gusta, Comentarios y Stories, cada una con su gráfico mensual y su tabla de cuentas más frecuentes.
  • Mensajes: lista de conversaciones (inbox y broadcast) con conteo de mensajes y última actividad; al seleccionar una, un mini-gráfico de actividad y un visor de contenido paginado (remitente, fecha, texto).
  • Conexiones:
    • Limpieza — la función original: compara un export de seguidores con uno de seguidos y muestra quién sigues que no te sigue de vuelta, con exportación a .txt/.csv.
    • Crecimiento — evolución en el tiempo de followers/following y conteos de amigos íntimos, bloqueados y solicitudes.
  • Explorador de archivos: árbol con todos los ficheros del export (recorrido recursivo, soporta la estructura real del zip de Instagram), con una tabla paginada que interpreta el contenido de cualquier JSON, sea cual sea su esquema interno — el respaldo genérico para categorías sin dashboard propio (anuncios, seguridad, información personal, apps...).
  • Dos formatos soportados para el análisis de no-seguidores: el HTML legado de Instagram y el JSON que exporta actualmente la plataforma — se detectan automáticamente por extensión.
  • Corrección de mojibake: Instagram exporta el JSON con los caracteres no-ASCII mal codificados ("Germán" en vez de "Germán"); se corrige en toda la aplicación antes de mostrarse.
  • Cache en disco: los agregados de analítica (especialmente sobre ficheros grandes, como un liked_posts.json de cientos de MB) se cachean en .cache/analytics/ y solo se recalculan si el fichero fuente cambia.
  • Tablas Model/View: el explorador y las tablas de analítica usan QTableView en vez de un widget por celda, para que ficheros con decenas de miles de filas sigan yendo fluidos.
  • Enlaces clicables y avatares por iniciales: cualquier URL detectada se muestra como hipervínculo real; cada usuario se muestra con un avatar circular de color estable generado a partir de su nombre (Instagram no incluye foto de perfil en sus exports).
  • Interfaz Fluent Design, con tema claro/oscuro automático según el de Windows, y gráficos (QtCharts) que se adaptan al mismo tema.

Stack técnico

Capa Tecnología Por qué
UI PySide6 + QFluentWidgets Fluent Design nativo de Windows 11, sin reinventar componentes
Gráficos PySide6.QtCharts Incluida en PySide6-Addons — cero dependencias nuevas, tema claro/oscuro coherente con el resto de la UI
Concurrencia QThread (AnalysisWorker, AggregateWorker) El parsing de ficheros de cientos de MB nunca bloquea el hilo de UI
Parsing json (stdlib) + BeautifulSoup4 Un ProfileParser (Strategy) por formato de export
Persistencia Cache JSON en disco, invalidada por mtime/tamaño Evita recalcular sobre ficheros que no han cambiado
Tests pytest, fixtures sintéticas Domino testeado sin Qt y sin depender de datos personales

Arquitectura

El proyecto separa el dominio (parsing y análisis, sin dependencias de UI) de la presentación (PySide6 + QFluentWidgets), siguiendo los principios SOLID:

core/                       # Dominio puro — testeable sin Qt
├── models.py                 # Profile, FileEntry, TableResult
├── exceptions.py              # Errores de dominio (EaseYourIGStatsError)
├── text.py                    # fix_mojibake
├── parsers/                   # Strategy: un parser por formato de export
│   ├── base.py                  # interfaz ProfileParser
│   ├── html_parser.py           # export HTML legado
│   ├── json_parser.py           # export JSON actual
│   └── factory.py                # elige parser según la extensión del fichero
├── services/
│   ├── non_followers_analyzer.py  # following - followers (Limpieza)
│   └── files_repository.py        # listado y normalización paginada de files/
└── analytics/                 # Agregados para el dashboard y las paginas
    ├── cache.py                  # AnalyticsCache: cache en disco por mtime/tamaño
    ├── categories.py              # localizacion de ficheros por sufijo de ruta
    ├── models.py                  # TimeSeriesPoint, RankedAccount
    ├── timeseries.py              # bucket_by_month, cumulative
    ├── ranking.py                  # top_accounts
    └── aggregators/
        ├── connections.py          # followers/following + metadatos relacionados
        ├── interactions.py         # likes, comentarios, stories
        ├── messages.py             # conversaciones + visor de contenido
        └── dashboard.py            # combina todo lo anterior para Resumen

ui/                          # Presentación — PySide6 + QFluentWidgets
├── app.py                    # arranque de QApplication y tema Fluent
├── main_window.py            # FluentWindow con navegacion (5 secciones)
├── pages/
│   ├── dashboard_page.py       # Resumen
│   ├── activity_page.py        # Actividad (likes/comentarios/stories)
│   ├── messages_page.py        # Mensajes
│   ├── connections_page.py     # Conexiones (envuelve AnalysisPage)
│   ├── analysis_page.py        # Limpieza de no-seguidores (sin cambios)
│   └── files_explorer_page.py  # Explorador generico
├── widgets/                   # componentes visuales reutilizables
│   ├── avatar.py                # avatar circular por iniciales
│   ├── link_label.py            # hiperenlace para la tabla de Limpieza
│   ├── link_delegate.py         # hiperenlace pintado en QTableView (sin widget por celda)
│   ├── table_model.py           # QAbstractTableModel generico
│   ├── charts.py                # helpers sobre QtCharts
│   ├── summary_card.py          # tarjeta de numero + caption
│   └── layout_utils.py          # clear_layout
└── workers.py                 # QThread: AnalysisWorker y AggregateWorker

tests/                       # Tests del dominio (sin Qt), contra fixtures sinteticas
└── fixtures/                  # HTML/JSON sintéticos de prueba (no datos reales)

Por qué esta separación:

  • SRP — cada módulo tiene una única responsabilidad: parsear, analizar, explorar ficheros o presentar. Cambiar la UI no afecta a la lógica de negocio, y viceversa.
  • OCP — soportar un nuevo formato de export o una nueva categoría de analítica solo requiere una nueva clase/agregador, sin tocar el resto.
  • LSPHtmlProfileParser y JsonProfileParser implementan la misma interfaz y son intercambiables para quien los use.
  • ISPProfileParser solo expone supports()/parse(), sin métodos irrelevantes para sus consumidores.
  • DIPNonFollowersAnalyzer, los agregadores y las páginas de la UI dependen de abstracciones (ParserFactory, AnalyticsCache), no de BeautifulSoup ni de json directamente.

Ingeniería de rendimiento

Un export real de Instagram con varios años de actividad puede rondar los 2 GB en más de 500 ficheros, con un solo liked_posts.json de más de 200 MB (100 000+ likes). Con eso como caso real de prueba, no como hipótesis:

  • Antes: una tabla QTableWidget con un QWidget (QLabel) por cada celda que pareciera un enlace. Con miles de filas, cada apertura de fichero se notaba; con el fichero de 100k+ filas, dejaba de ser usable.
  • Después: QTableView + QAbstractTableModel genérico, con un QStyledItemDelegate que pinta los hipervínculos directamente sobre la vista — cero widgets por fila — más paginación (500 filas por página) en el explorador de ficheros.
  • Cache en disco por huella de fichero (AnalyticsCache): cada agregado del dashboard se computa una vez y se guarda en .cache/analytics/, con clave de invalidación por tamaño + mtime del fichero fuente (nunca por releerlo, para no anular el propio ahorro). Resultado sobre el fichero de 200+ MB: ~2 s en frío, ~0.4 s en caliente.
  • Todo el parsing pesado corre en un QThread (AggregateWorker genérico, reutilizado por las cinco páginas), nunca en el hilo de UI — la ventana permanece responsive incluso mientras se procesa el fichero más grande del export.

Empezando

Requisitos

  • Python 3.10 o superior (probado con 3.14).
  • Windows 10/11 (la interfaz está pensada para el lenguaje visual Fluent de Windows 11; funciona en otros sistemas pero sin la integración nativa).

Instalación

# Crear y activar un entorno virtual (si no existe ya .venv)
python -m venv .venv
.venv\Scripts\Activate.ps1

# Instalar dependencias
pip install -r requirements.txt

Cómo obtener tus datos de Instagram

  1. En Instagram: Ajustes → Tu actividad → Descargar tu información.
  2. Solicita el export en formato JSON (recomendado) o HTML.
  3. Descomprime el .zip recibido. Dentro encontrarás carpetas como connections/followers_and_following/, your_instagram_activity/likes/, your_instagram_activity/messages/, etc.
  4. Copia esa carpeta (o su contenido) dentro de files/ en este proyecto. No hace falta aplanar la estructura: la aplicación la recorre de forma recursiva y encuentra cada fichero conocido esté donde esté.

Ejecución

python main.py

Se abrirá la ventana principal con cinco secciones: Resumen, Actividad, Mensajes, Conexiones (con la pestaña Limpieza de no-seguidores) y Explorador de archivos.

Tests

pip install pytest   # dependencia de desarrollo, no de runtime
python -m pytest tests/

Los tests cubren la capa de dominio (parsers, analizador de no-seguidores, FilesRepository, fix_mojibake, resolución de categorías, cache y cada agregador) usando fixtures sintéticas en tests/fixtures/ — nunca contra la carpeta files/ real, que es el export personal de quien ejecute la app.

Estructura del repositorio

EaseYourIGStats/
├── main.py                  # entrypoint de la aplicación
├── requirements.txt
├── core/                    # dominio (parsers, servicios, analytics)
├── ui/                      # interfaz gráfica
├── tests/                   # tests del dominio
├── files/                   # tus exports de Instagram (.json o .html) — ignorado por git
└── .cache/                  # cache en disco de analítica (se regenera sola) — ignorado por git

Roadmap

El proyecto se construyó a propósito como un MVP en fases. Próximas categorías del export con dashboard propio, hoy accesibles vía el Explorador de archivos genérico:

  • Anuncios e intereses (temas sugeridos, anunciantes, categorías usadas para segmentarte)
  • Seguridad (histórico de logins, dispositivos, IPs)
  • Información personal y preferencias
  • Exportar el Resumen completo a PDF/imagen

Privacidad

Tus datos de Instagram nunca salen de tu máquina: no hay llamadas de red, ni telemetría, ni servicios en la nube. La carpeta files/ (tu export real) y .cache/ (los agregados calculados sobre él) están en .gitignore — nunca se suben al repositorio.

Licencia

Añade aquí la licencia que prefieras (por ejemplo, MIT) si vas a publicar el repositorio.

About

Desktop app that turns your Instagram data export into a visual dashboard: activity, messages, connections, and non-follower cleanup. 100% local — your data never leaves your machine.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages