Skip to main content

Overview

The LinkedIn Job Analyzer provides flexible data export functionality, allowing users to save extracted job data and AI insights in multiple formats. The export system uses the Factory Pattern to instantiate the appropriate exporter based on user preference.
Supported formats: JSON and Excel (.xlsx)

Architecture

The export system consists of three main components:

Base Exporter Interface

base_exporter.py
from abc import ABC, abstractmethod
from typing import Dict

class DataExporter(ABC):
    """Interfaz base para todos los exportadores de datos."""
    
    @abstractmethod
    def exportar(self, datos: Dict, ruta_salida: str) -> str:
        """Debe retornar la ruta donde se guardó el archivo."""
        pass

Factory Implementation

The ExporterFactory dynamically selects the correct exporter:
exporter_factory.py:4-14
class ExporterFactory:
    """Fábrica que decide qué exportador instanciar."""
    
    @staticmethod
    def obtener_exportador(formato: str):
        if formato == 'json':
            return JSONExporter()
        elif formato == 'excel':
            return ExcelExporter()
        else:
            raise ValueError(f"Formato {formato} no soportado")
The factory pattern makes it easy to add new export formats without modifying existing code

Export Formats

JSON Export

The JSONExporter saves data in a human-readable JSON format with proper UTF-8 encoding for international characters.
json_exporter.py:5-21
class JSONExporter(DataExporter):
    """
    Exportador responsable de guardar los diccionarios de datos en formato .json.
    """
    
    def exportar(self, datos: Dict, ruta_salida: str) -> str:
        """
        Guarda los datos en un archivo JSON usando la ruta proporcionada.
        """
        # Abrimos el archivo en modo escritura ('w') con soporte para caracteres latinos (utf-8)
        with open(ruta_salida, 'w', encoding='utf-8') as f:
            # ensure_ascii=False permite guardar acentos y ñ correctamente
            # indent=4 le da un formato legible para humanos
            json.dump(datos, f, ensure_ascii=False, indent=4)
        
        print(f"[DATOS] Archivo JSON guardado con éxito: {ruta_salida}")
        return ruta_salida

Features

UTF-8 Encoding

Preserves accented characters and special symbols

Pretty Printing

4-space indentation for human readability

ensure_ascii=False

Allows native storage of non-ASCII characters

Compact

Single file with all data

Example Output

resultado_python_developer.json
{
    "termino_busqueda": "Python Developer",
    "titulo_oferta": "Senior Python Backend Developer",
    "url": "https://www.linkedin.com/jobs/view/123456789",
    "fecha_extraccion": "2026-03-07 14:23:15",
    "habilidades": [
        "Python 3.10+",
        "FastAPI",
        "PostgreSQL",
        "Docker",
        "AWS",
        "5+ años de experiencia"
    ],
    "resumen_ia": "**Objetivo del Rol**: Desarrollador backend especializado en Python..."
}

Usage Example

Using the Export System
from exportadores.exporter_factory import ExporterFactory

# Prepare data
data = {
    'termino_busqueda': 'Python Developer',
    'titulo_oferta': 'Senior Python Backend Developer',
    'url': 'https://www.linkedin.com/jobs/view/123456789',
    'fecha_extraccion': '2026-03-07 14:23:15',
    'habilidades': [
        'Python 3.10+',
        'FastAPI',
        'PostgreSQL',
        'Docker',
        'AWS'
    ],
    'resumen_ia': 'AI-generated summary...'
}

# Export to JSON
json_exporter = ExporterFactory.obtener_exportador('json')
json_path = json_exporter.exportar(data, 'results/job_analysis.json')
print(f"JSON saved to: {json_path}")

# Export to Excel
excel_exporter = ExporterFactory.obtener_exportador('excel')
excel_path = excel_exporter.exportar(data, 'results/job_analysis.xlsx')
print(f"Excel saved to: {excel_path}")

Data Structure

Both exporters expect a dictionary with the following schema:
termino_busqueda
string
required
The original search term used for the job query
titulo_oferta
string
required
The extracted job title
url
string
required
The LinkedIn job posting URL
fecha_extraccion
string
required
Timestamp when the data was extracted (ISO format recommended)
habilidades
array
required
List of extracted skills and requirements
resumen_ia
string
AI-generated summary (only if analysis was requested)

Error Handling

The factory raises a ValueError if an unsupported format is requested
try:
    exporter = ExporterFactory.obtener_exportador('pdf')
except ValueError as e:
    print(f"Error: {e}")  # Output: Error: Formato pdf no soportado

Handling Export Failures

Both exporters may raise exceptions during file operations:
try:
    exporter = ExporterFactory.obtener_exportador('json')
    path = exporter.exportar(data, '/invalid/path/file.json')
except PermissionError:
    print("Cannot write to directory")
except Exception as e:
    print(f"Export failed: {e}")

Dependencies

import json
from typing import Dict
No external dependencies - uses Python standard library

Extending the System

To add a new export format, follow these steps:
1

Create Exporter Class

Inherit from DataExporter and implement the exportar method
from .base_exporter import DataExporter
from typing import Dict

class CSVExporter(DataExporter):
    def exportar(self, datos: Dict, ruta_salida: str) -> str:
        # Implementation here
        return ruta_salida
2

Update Factory

Add the new format to the factory’s conditional logic
@staticmethod
def obtener_exportador(formato: str):
    if formato == 'json':
        return JSONExporter()
    elif formato == 'excel':
        return ExcelExporter()
    elif formato == 'csv':
        return CSVExporter()
    else:
        raise ValueError(f"Formato {formato} no soportado")
3

Test

Verify the new exporter works correctly
exporter = ExporterFactory.obtener_exportador('csv')
path = exporter.exportar(test_data, 'output.csv')

Best Practices

Use UTF-8 Encoding

Always specify encoding='utf-8' when writing files to support international characters

Validate Data First

Check that all required fields exist before attempting export

Handle Exceptions

Wrap export operations in try-except blocks to gracefully handle failures

Return File Path

Always return the output path for confirmation and further processing

Build docs developers (and LLMs) love