---
title: "Cómo automatizar el análisis de logs con Python y Pandas"
description: "Deje de adivinar cómo ve Google su web. Con Python y Pandas analice los logs, optimice el crawl budget y detecte las «páginas zombi» que dañan su SEO."
url: "https://kodokalabs.com/es/intelligence-hub/search-intelligence/analisis-de-logs-con-python-y-pandas/"
language: es
published: 2025-12-18
updated: 2026-11-07
---

# Cómo automatizar el análisis de logs con Python y Pandas

## La «caja negra» del SEO está en su servidor.

La mayoría de los profesionales del SEO vuelan a ciegas. Se apoyan en crawlers de terceros (como Screaming Frog o Ahrefs) para simular lo que ve Google. Miran los datos muestreados de Google Search Console (GSC) para adivinar lo que ocurre.

Pero una simulación no es la realidad. Y una muestra no es exactitud.

La única fuente de verdad en el SEO es su **archivo de logs del servidor**. Este archivo registra todas y cada una de las peticiones que recibe su servidor, incluida cada visita de Googlebot. Le dice con exactitud:

- Qué páginas visita Googlebot con más frecuencia (y con menos).
- Dónde se desperdicia su «crawl budget» en parámetros inútiles.
- Qué páginas de alto valor se ignoran por completo.

Tradicionalmente, el análisis de logs era caro (las [herramientas](../../pages/en/tools.md) SaaS empresariales cuestan más de 900 €/mes) o difícil (Excel se bloquea a partir de un millón de filas).

En kōdōkalabs lo resolvemos con **Python.**

Esta guía es un tutorial técnico para construir su propio motor de análisis de logs con la biblioteca Pandas. Le llevaremos de «adivinar» a «saber» en menos de 50 líneas de código.

## Parte 1: Por qué no puede ignorar los logs

Si gestiona un sitio de más de 5.000 páginas (e-commerce, editorial, SaaS B2B), el **crawl budget** es un factor de posicionamiento. Google no tiene recursos infinitos. Si gasta su presupuesto rastreando sus filtros, errores 404 y redirecciones, no le quedará presupuesto para descubrir sus nuevas «páginas de negocio».

### El fenómeno de las «páginas zombi»

Nuestros datos internos indican que, en los sitios grandes, **el 40 % de las páginas no recibe ningún rastreo al mes.**
Son las «páginas zombi». Existen en su sitio, pero para Google están muertas.

- Las **herramientas SaaS** no se lo mostrarán (solo muestran lo que han encontrado).
- **GSC** no se lo mostrará (agrega los datos).
- **Python** lo revela al instante.

## Parte 2: La pila tecnológica (gratuita y potente)

Vamos a replicar la funcionalidad de una herramienta empresarial de 9.000 € sin pagar nada.

- **Lenguaje:** [Python 3.10+](https://www.python.org/)
- **Biblioteca:** [Pandas](https://pandas.pydata.org/) (para manipular datos a gran velocidad).
- **Biblioteca:** [Advertools](https://advertools.readthedocs.io/en/master/) (una biblioteca fantástica, específica para SEO, de Elias Dabbas).
- **Entrada:** sus archivos de logs de acceso en bruto (normalmente .log o .gz de Nginx/Apache).

## Parte 3: El tutorial (de los datos en bruto al insight)

Aquí es donde falla el 99 % de los profesionales de marketing. Dedican semanas a la plantilla y minutos a los datos.
**Hay que dedicar el 80 % del tiempo a los datos.**

### Paso 1: Acceder a los datos

Pida a su equipo de DevOps o a su proveedor de hosting los «logs de acceso en bruto» de los últimos 30 días. Necesita los logs de Nginx o Apache sin procesar.

### Paso 2: El script de parseo

Los logs en bruto son cadenas de texto desordenadas. Tenemos que convertirlos en un DataFrame (una tabla) estructurado para poder hacerles preguntas.

Usaremos advertools porque se encarga del parseo con expresiones regulares de forma automática.

```python
import advertools as adv
import pandas as pd

# 1. Parsear el archivo de logs (admite el formato combined estándar)
# convirtiendo el .log en bruto en un archivo Parquet estructurado, por velocidad
adv.logs_to_df(
log_file='access.log',
output_file='logs_output.parquet',
errors_file='errors.txt',
log_format='combined'
)

# 2. Cargar los datos en Pandas
df = pd.read_parquet('logs_output.parquet')

# 3. Convertir la marca de tiempo a objeto datetime (clave para el análisis de series temporales)
df['datetime'] = pd.to_datetime(df['datetime'], format='%d/%b/%Y:%H:%M:%S %z')

print(f"Total Requests Loaded: {len(df)}")
```

### Paso 3: Filtrar por Googlebot

Internet está lleno de ruido (scrapers, tráfico de usuarios, bots maliciosos). Solo nos interesa el VIP: Googlebot.
Advertencia: no se fíe únicamente de la cadena User Agent (puede falsificarse). En un entorno de producción hay que verificar la dirección IP con la lista de Google. Para este tutorial filtraremos por User Agent, para simplificar.

```python
# Crear un filtro para los User Agents de Googlebot
googlebot_filter = df['user_agent'].str.contains('Googlebot', case=False, na=False)

# Crear un DataFrame limpio solo con las visitas de Googlebot
google_df = df[googlebot_filter].copy()

print(f"Total Googlebot Hits: {len(google_df)}")
```

![Captura abstracta de datos de logs sobre fondo oscuro: líneas finas de texto en azul y bloques rojos de distinto tamaño, que ilustran el análisis de los hits de Googlebot en un archivo de logs.](https://kodokalabs.com/assets/media/2025/12/kodokalabs-02-003-the-modern-seo-stack-automating-log-file-analysis-with-python-and-pandas-the-analysis-1024x439.webp)

## Parte 4: El análisis (hacer las preguntas correctas)

Ahora que tenemos datos limpios, podemos responder a las preguntas estratégicas que impulsan los ingresos del SEO.

### Análisis A: Distribución de códigos de estado (el chequeo de salud)

¿Los bots reciben códigos 200 (éxito) o se topan con 301 (redirecciones) y 404 (errores)?

```python
# Contar los códigos de estado
status_counts = google_df['status'].value_counts()
print(status_counts)

# Calcular el porcentaje
status_percent = google_df['status'].value_counts(normalize=True) * 100
print(status_percent)
```

**Conclusión estratégica:**

- Si los 3xx superan el 10 %: tiene cadenas de redirecciones que malgastan presupuesto.
- Si los 4xx superan el 5 %: está enviando a Google a callejones sin salida. Priorice la corrección de esos enlaces de inmediato.
- Si los 5xx superan el 1 %: su servidor es inestable cuando visita Google. Es una emergencia crítica de posicionamiento.

### Análisis B: Secciones más rastreadas (el chequeo de prioridades)

Google le dice lo que considera importante por dónde invierte su tiempo. Veamos qué carpetas reciben más atención.

```python
# Extraer la primera carpeta de la ruta de la URL
google_df['folder'] = google_df['request'].str.split('/').str[1]

# Contar las visitas por carpeta
folder_counts = google_df.groupby('folder').size().sort_values(ascending=False)
print(folder_counts.head(10))
```

**Conclusión estratégica:**

- ¿Su /blog/ recibe el 80 % del rastreo pero aporta el 5 % de los ingresos?
- ¿Se está ignorando su carpeta /products/?
- Acción: si dominan las carpetas de bajo valor, bloquéelas en robots.txt o mejore el enlazado interno hacia las carpetas de alto valor.

### Análisis C: Identificar las «páginas zombi»

Este es el script que marca la diferencia. Hay que comparar «todas las páginas conocidas» (de su sitemap) con las «páginas rastreadas» (de los logs).
Requisito previo: descargue su sitemap XML a un CSV o una lista.

```python
# Cargar las URL de su sitemap
sitemap_urls = pd.read_csv('sitemap_urls.csv')['url'].tolist()

# Obtener las URL únicas rastreadas por Google
crawled_urls = google_df['request'].unique().tolist()

# Calcular la diferencia (páginas en el sitemap pero NO en los logs)
zombie_pages = set(sitemap_urls) - set(crawled_urls)

print(f"Total Pages in Sitemap: {len(sitemap_urls)}")
print(f"Total Pages Crawled: {len(crawled_urls)}")
print(f"Zombie Pages (Zero Crawls): {len(zombie_pages)}")

# Exportar las zombi a CSV para el equipo de contenidos
pd.DataFrame(list(zombie_pages), columns=['url']).to_csv('zombie_pages.csv', index=False)
```

**Conclusión estratégica:**

- Una página zombi no tiene ninguna posibilidad de posicionarse ni de actualizarse en el índice.
- **Acción:** revise el enlazado interno. ¿Esta página no recibe ningún enlace entrante? Añádala a su flujo de trabajo del «agente de enlazado interno».

## Parte 5: Análisis avanzado de la «velocidad de rastreo»

Para sitios de noticias o editoriales de alta frecuencia, saber con qué rapidez descubre Google el contenido nuevo es clave. Podemos calcular el equivalente al «Time to First Byte» del rastreo.

```python
# Remuestrear los datos por hora para ver las tendencias de frecuencia de rastreo
hourly_crawl = google_df.set_index('datetime').resample('H').size()

# Representarlo (requiere matplotlib)
import matplotlib.pyplot as plt
hourly_crawl.plot(title="Googlebot Hits Per Hour", figsize=(12, 6))
plt.show()
```

Si ve picos enormes, correlaciónelos con sus despliegues. ¿Un nuevo despliegue de código provocó un nuevo rastreo? ¿O un error del servidor provocó una caída?

## Parte 6: Automatizar el pipeline

Hacerlo una vez es una auditoría. Hacerlo cada día es **DevOps.**
En kōdōkalabs envolvemos este script en un contenedor Docker y lo ejecutamos cada lunes por la mañana.

- **Cron job:** descarga los logs de AWS S3.
- **Script:** ejecuta el análisis.
- **Alertas:** si Zombie\_Rate supera el 30 % o Error\_Rate supera el 5 %, envía una alerta de Slack al canal de SEO técnico.

Así se pasa del «SEO reactivo» (arreglar las cosas cuando el tráfico ya ha caído) al «SEO proactivo» (arreglarlas antes de que a Google le importen).

## Parte 7: La ventaja de «kōdōkalabs»

¿Por qué compartimos este código? Porque tener la herramienta no es lo mismo que tener la estrategia.
Saber que tiene 4.000 páginas zombi es el primer paso.
Saber cuáles de ellas hay que eliminar, cuáles fusionar y cuáles necesitan una inyección de schema es donde entra el **estratega humano**.

## ¿Confía sus logs a una hoja de cálculo?

¿O prefiere diseñar su crawl budget?[Reservar una auditoría técnica de logs](#contact)
