Back to "Resucitando mi viejo blog con Archive.org y un montón de C#"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

.NET Archive.org Imported

Resucitando mi viejo blog con Archive.org y un montón de C#

Monday, 24 November 2025

Así que podrías haber notado cientos de Entradas de blog "nuevas" Aparecen recientemente. Bueno, no son nuevos en absoluto - son viejos. Como, 2004 viejo. Finalmente construí una herramienta para rescatar mi contenido del cementerio digital que era mi antiguo blog en la mayoríalucid.co.uk.

Por qué Archive.org es absolutamente brillante

Antes de que me sumerja en las cosas técnicas, tengo que dar un grito masivo a la Archivo de Internet Esta organización sin fines de lucro ha estado archivando silenciosamente la web desde 1996, preservando miles de millones de páginas web que de otro modo se perderían para siempre.

Piensa en eso por un segundo. Cada entrada de blog que escribiste en 2005, cada página de GeoCities, cada perfil de MySpace - hay una probabilidad decente de que todavía sea accesible a través de Archive.org. Esencialmente están dirigiendo un museo de toda la Internet, financiado por donaciones y subvenciones.

Cuando mi antiguo proveedor de alojamiento desapareció (junto con mis copias de seguridad porque era SMART así), pensé que todo ese contenido se había ido para siempre. Resulta que la Wayback Machine había estado fotografiando diligentemente mi sitio durante años. Archive.org literalmente salvó más de 6 años de mi historia de blogs.

Si usted nunca ha donado a ellos, considere hacerlo. Están preservando nuestra historia digital colectiva.

El problema: Mi blog fue un desastre

He aquí la cosa acerca de la ejecución de un blog de 2004 a 2010 - las tecnologías web cambiaron un montón durante ese tiempo. Y aparentemente, cambié mi configuración de blogging por lo menos tres veces:

  1. Primeros días (2004): Algo homebrew ASP.NET con contenido envuelto en <div class="post"> dentro de una <form> elemento (porque todo era una forma en ese entonces)
  2. Período intermedio: Estructura de plantilla diferente, fechas en diferentes lugares
  3. Años posteriores: Otra reestructuración con selectores ligeramente diferentes

De la memoria que utilizaba algo personalizado entonces SubTexto (Phil Haack blogging cosa). Seguido por Community Server (a Telligent thing ASP.NET utilizado para alojar sitios, por AOTHER ex ASP, NET PM Rob Howard) . TODOS los cuales tenían diferentes formas de actualización y diferentes maneras de mostrar contenido.

Esto significaba que cualquier herramienta de extracción necesitaba ser lo suficientemente flexible para manejar múltiples estructuras HTML. Un rascador de "un tamaño se ajusta a todos" no iba a cortarlo.

Introduzca el archivoOrgImporter

Construí ArchivoOrgImporter para resolver este problema muy específico. Es una aplicación de consola .NET 9.0 que:

  1. Respeta los límites de uso de Archive.org - Son una organización sin fines de lucro con donaciones, por lo que martillar sus servidores sería una cosa terrible para hacer
  2. Descargas de páginas archivadas entre fechas configurables
  3. Extrae contenido de blog de múltiples estructuras HTML
  4. Genera la limpieza de Markdown en mi formato de blog actual
  5. Utiliza Ollama para generar etiquetas útiles - porque por qué no le lanzas un poco de magia LLM?

Cómo funciona

La herramienta sigue una arquitectura de tuberías con tres fases principales:

Archive.org CDX API → Download HTML → Convert to Markdown → Generate Tags → Output Files

Fase 1: Consultar el archivo

La herramienta utiliza Archive.org's API de CDX para encontrar todas las instantáneas archivadas de mi blog. Esta API devuelve una lista de URLs capturadas con marcas de tiempo, tipos MIME y códigos de estado HTTP.

// The CDX query builds a URL like this:
// https://web.archive.org/cdx/search/cdx?url=mostlylucid.co.uk/posts/&output=json&collapse=urlkey

Los collapse=urlkey parámetro es inteligente - devuelve sólo la última instantánea para cada URL único, lo que reduce drásticamente el número de duplicados que necesita para tratar.

También uso patrones regex para filtrar URLs. Mis mensajes antiguos siguieron el patrón /posts/[number].aspx, así que:

{
  "IncludePatterns": ["/posts/\\d+\\.aspx$"]
}

De esta manera sólo tomo publicaciones de blog reales, no las páginas de archivo, páginas de categoría, o RSS feeds.

Fase 2: Ser un buen ciudadano con tasa límite

Archive.org es un servicio público. No tienen el presupuesto de infraestructura de Google o Amazon. Así que el descargador es deliberadamente conservador:

// Default: 5 seconds between requests, single-threaded downloads
"RateLimitMs": 5000,
"MaxConcurrentDownloads": 1

Sí, esto significa que descargar cientos de publicaciones lleva un tiempo, pero es lo correcto. La herramienta también maneja 429 (límite de tasa) respuestas con gracia con un retroceso exponencial.

También hay algo de limpieza necesaria para los archivos descargados. Archive.org añade scripts de barra de herramientas y reescribe URLs en el HTML capturado. El descargador elimina todo eso:

private static string CleanWaybackArtifacts(string html)
{
    // Remove the interactive Wayback toolbar
    html = WaybackToolbarRegex().Replace(html, string.Empty);
    // Remove playback.archive.org script references
    html = WaybackScriptRegex().Replace(html, string.Empty);
    // Strip archival metadata comments
    html = WaybackCommentRegex().Replace(html, string.Empty);
    // Rewrite archived URLs back to original paths
    html = WaybackUrlRewriteRegex().Replace(html, "$1$2");
    return html;
}

El mango de patrones regex:

  • <!-- BEGIN WAYBACK TOOLBAR INSERT -->...<!-- END WAYBACK TOOLBAR INSERT --> - la barra de herramientas HTML
  • <script> referenciación de etiquetas playback.archive.org
  • Archivo de metadatos comentarios
  • Prefijos URL como https://web.archive.org/web/20040527/ que se preparan a todos los enlaces

Fase 3: La pesadilla de extracción de contenido

Aquí es donde las cosas se ponen interesantes. ¿Recuerdas que mencioné que mi blog cambió de estructura tres veces? Así es como lo manejé.

La extracción primaria utiliza un selector CSS:

{
  "ContentSelector": "div.post"
}

Pero aquí hay una rareza divertida - en algunas versiones de mi antiguo sitio, el div.post estaba EN EL INTERIOR <form> elemento. El código tiene que extraer el contenido ANTES de eliminar los elementos no deseados, de lo contrario eliminar <form> etiquetas bombardearían el contenido real del blog:

// In ConvertFileAsync - the order here is critical
var contentNode = ExtractMainContent(doc);
if (contentNode == null)
{
    _logger.LogWarning("Could not find main content in {File}", htmlFilePath);
    return articles;
}

// NOW we can safely remove unwanted elements from within the extracted content
RemoveUnwantedElementsFromNode(contentNode);

Los ExtractMainContent método utiliza una búsqueda jerárquica para encontrar el contenido:

// For selectors like "div.post", split and search by element + class
node = doc.DocumentNode.Descendants()
    .FirstOrDefault(n =>
        n.Name.Equals(elementName, StringComparison.OrdinalIgnoreCase) &&
        HasExactClass(n, className));

La herramienta también tiene selectores de reserva si el primario falla:

  1. div.blogpost, div.singlepost, article
  2. #content, #main-content, #PostBody
  3. .post-content, .entry-content, .article-content
  4. Por último, sólo el <body> si todo lo demás falla

Luego hay una larga lista de elementos para eliminar DESPUÉS de la extracción de contenido:

{
  "RemoveSelectors": [
    "nav", "header", "footer", ".sidebar", ".advertisement",
    ".comments", ".social-share", ".related-posts", "script",
    "style", "noscript", "iframe", "#commentform", ".postNav"
  ]
}

Fase 4: Generación de Markdown

Una vez que tengamos contenido HTML limpio, Marcado inverso se encarga de la pesada elevación de convertir a GitHub Markdown con sabor a GitHub.

Pero la salida necesitaba un poco de post-procesamiento. El viejo HTML a menudo tenía una sangría extraña que confundiría a los parsers de Markdown (líneas identificadas se convierten en bloques de código!).

// Removes leading whitespace from non-code lines
// Preserves code block formatting (respects ``` fences)
// Removes excessive blank lines (max 2 consecutive)

La salida final incluye el formato principal de mi blog:

# Article Title




Article content here...

Fase 5: Generación de etiquetas con potencia LLM

Ahora para la parte divertida. Los posts de blog antiguos a menudo no tenían etiquetas en absoluto, o etiquetas que no tenían sentido para mi estructura actual del sitio. Así que integré Ollama para analizar contenido y generar etiquetas relevantes.

La configuración es sencilla:

{
  "Ollama": {
    "BaseUrl": "http://localhost:11434",
    "Model": "gemma3:4b",
    "Temperature": 0.3,
    "MaxTags": 5,
    "Enabled": true
  }
}

Utilizo gemma3:4b La baja temperatura (0,3) mantiene la salida consistente – no queremos alucinaciones creativas en nuestras etiquetas. Nota; para mi blog esto funcionó como si las publicaciones fueran cortas, si la tuya es más larga asegúrese de ver las técnicas de troceado y resumen que encajan en la ventana de contexto de su modelo.

Manejo de puestos más largos

Aquí hay una limitación práctica: los LLMs tienen ventanas de contexto, y bombear un blog entero en ellos para la generación de etiquetas es derrochador. La herramienta trunca el contenido a 3000 caracteres:

var truncatedContent = content.Length > 3000
    ? content[..3000] + "..."
    : content;

Para la generación de etiquetas, los primeros 3000 caracteres suelen contener suficiente contexto para entender de qué se trata el post. El prompt instruye al modelo a centrarse en categorías específicas de tecnología:

Generate up to 5 tags, short (1-3 words), focusing on:
.NET, C#, ASP.NET, JavaScript, Docker, Database, API, Security, DevOps, Cloud

El análisis de la respuesta es a la defensiva – si Ollama devuelve basura o tiempos fuera, sólo tenemos una lista de etiquetas vacía en lugar de romper todo el oleoducto.

Extracción de fecha: un enfoque multi-estrategia

Encontrar la fecha de publicación original es sorprendentemente complicado. Mi antiguo blog almacena fechas en diferentes lugares a lo largo de los años. La herramienta intenta múltiples estrategias:

  1. Selector configurado (por ejemplo, .postfoot)
  2. Metaetiquetas: article:published_time, DC.date.issued
  3. HTML5 <time> elementos
  4. Clases de fechas comunes: .date, .post-date, .entry-date
  5. Patrones Regex en HTML en bruto (formato ISO, separado por barras, etc.)
  6. Retroceso: La fecha de la instantánea de archivo en sí mismo

Un formato particularmente molesto fue mi vieja plantilla de blog "publicada el jueves, 27 de mayo de 2004 11:21 PM" cadena. Hay análisis específico para eso.

La orquestación del oleoducto

El bit arquitectónico más cool es cómo la descarga y conversión se ejecutan en paralelo usando canales .NET:

var channel = Channel.CreateBounded<string>(10);

// Producer: downloads and writes file paths to channel
// Consumer: reads file paths and converts to markdown

Esto significa que la conversión comienza tan pronto como las primeras descargas de archivos, en lugar de esperar a que todas las descargas para completar. La capacidad limitada (10 elementos) proporciona contrapresión - si la conversión se queda atrás, la descarga se ralentiza para coincidir.

Limitaciones y gotchas

Seamos honestos sobre lo que esta herramienta no puede hacer:

  1. Es muy específico para MI blog – Los selectores, patrones y extracción de fechas están todos sintonizados para mayoritariamentelucid.co.uk. Necesitarías personalizar todo para un sitio diferente.

  2. Archive.org no lo tiene todo – Algunas páginas no fueron archivadas, o fueron archivadas con CSS/imágenes rotas.

  3. Las imágenes son el mejor esfuerzo - La herramienta intenta descargar imágenes de la máquina Wayback, pero muchas simplemente se han ido para siempre.

  4. Eslabones muertos en todas partes - Enlaces externos desde 2004 punto a sitios que ya no existen. Estoy trabajando en una solución separada para esto (la sustitución automática de enlaces Archive.org en un middleware - entrada de blog pronto!).

  5. Las etiquetas LLM son imperfectas – Las etiquetas generadas por Ollama son generalmente sensatas, pero ocasionalmente se olvidan de la marca. Se recomienda una revisión manual.

  6. Truncado de la API de CDX – Para sitios con miles de páginas, la API de CDX puede devolver resultados truncados. El código maneja esto con gracia, pero es posible que te pierdas algunas páginas.

Corriendo.

Si desea adaptar esto para su propio sitio (necesitará personalización), los comandos son:

# Full pipeline (download + convert)
dotnet run -- full

# Just download HTML from Archive.org
dotnet run -- download

# Just convert existing HTML files to Markdown
dotnet run -- convert

La herramienta soporta apagado elegante (Ctrl+C) y puede reanudarse desde donde lo dejó, ya que los archivos se cachean localmente.

Los resultados

Después de ejecutar esto en mi antiguo blog, recuperé publicaciones que se remontan a 1 de enero de 2004 y antes! Leer a través de ellos es un viaje fascinante a través del tiempo. Web discusiones de desarrollo de antes de jQuery existió. Posts sobre tecnologías que ahora son completamente obsoletos. Y algunas opiniones embarazosas que mantuve como un desarrollador más joven.

Usted puede encontrar todos los mensajes importados usando el Importado etiqueta de categoría.

¿Qué sigue?

El contenido importado tiene un montón de enlaces muertos – esa es la naturaleza del contenido web de 20 años de antigüedad. construyó una solución de middleware que:

  1. Detectar 404s para URLs antiguas
  2. Encuentre automáticamente la instantánea de Archive.org más cercana
  3. Redirigir o mostrar la versión archivada

Envolver

Construir esta herramienta fue un proyecto de fin de semana que se convirtió en algo realmente útil. Si has perdido contenido de un blog antiguo, hay una oportunidad decente Archive.org lo tiene. Y si te sientes cómodo con C#, las técnicas aquí (consulta de la API de CDX, extracción de contenido HTML, generación Markdown, etiquetado LLM) podrían adaptarse para su propio proyecto de recuperación.

El código está en github.com/scottgal/mostlylucid.nugetpackagesNo es una biblioteca pulida – es una herramienta diseñada específicamente para mi situación específica – pero podría darte ideas para tus propias aventuras de archivo.

Y en serio, vayan a donar a Archive.org. Están haciendo un trabajo importante.

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.