org及许多C##的旧博客与档案馆. (中文 (Chinese Simplified))

org及许多C##的旧博客与档案馆.

Monday, 24 November 2025

//

4 minute read

所以,你可能已经注意到 数百个 “新”博客文章 近来才出现。嗯,他们根本不是新人,他们已经老了。就像,2004年老了。我终于建立了一个工具,从数字墓地中拯救我的内容,那是我在Mostlucid.co.uk的旧博客。

为什么档案馆. org是绝对辉煌的

在我潜入技术领域之前 我得大呼大叫 Internet 归档 这个非营利组织自1996年以来一直悄悄地将网络归档,保存数十亿个网页,否则这些网页将永远丢失。

想想看。你2005年写的每一篇博客文章, 每一个地理城市页面,每个MySpace简介 仍然可以通过档案馆进入。org。他们基本上经营着一个整个互联网的博物馆, 经费来自捐款和赠款。

当我的老主机提供商失踪(加上我的备份是因为我是SMART这样的)时,我以为所有内容都永远消失了。 事实证明Wayback机器多年来一直在辛勤地拍摄我的网站。 档案馆.org 确实保存了我6年以上的博客历史。

如果你从未捐过钱给他们,请考虑一下,他们正在保护我们的集体数字历史。

问题:我的博客一团糟

从2004年到2010年, 网络科技改变了LOT。 显然,我至少更改了三次博客设置:

  1. 《早日》(2004年):一些家庭兄弟 ASP.NET 的东西,内容包裹在 <div class="post"> 内内a <form> 元素(因为当时一切都是一种形式)
  2. 中 中 期:不同的模板结构、不同地点的日期和模板结构不同
  3. 后来年份:又一次改组,选择者略有不同

从记忆中它使用了一些自定义的东西 子图文 (Phil Haack的博客文章)。 线 案 案 案 案 案 案 案 案 ASP.NET过去用于主办网站,由另一个前ASP,NET PM Rob Howard提供。 所有这些网站都有不同的更新方式和展示内容的不同方式。

这意味着任何提取工具都需要足够灵活的处理多个 HTML 结构。 一个“ 一刀切”的剪切器不会切开它 。

输入归档Org进口器

我建造的 归档导入器 要解决这个非常特殊的问题。 这是一个.NET 9. 0 控制台应用程序, 即:

  1. org的用途限制 - 他们是一个非营利 运行的捐赠, 所以敲敲他们的服务器 会是一个可怕的事情做
  2. 在可配置日期之间下载存档页面
  3. 从多个 HTML 结构中提取博客内容
  4. 生成清洁标记 以我当前博客格式
  5. 生成有用标签的 Ostellama - 为什么不扔一些LLM魔法呢?

如何运作

该工具遵循管道结构,分为三个主要阶段:

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

第1阶段:查询档案

该工具使用档案馆.org CDX API 此 API 返回包含时间戳、 MIME 类型和 HTTP 状态代码的被捕获的 URL 列表 。

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

缩略 collapse=urlkey 参数是智能的 - 它只返回每个独有的 URL 的最新快照, 这会显著减少您需要处理的复制件数量 。

我还使用 Regex 模式过滤 URL 。 我的旧日日志遵循了此模式 /posts/[number].aspx因此:

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

而不是档案页、分类页或RSS接口。

第2阶段:成为有利率限制的好公民

Google或Amazon没有基础设施预算。 因此下载者故意保守:

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

是的, 这意味着下载 数百 个文章需要一段时间。 但这样做是正确的。 该工具也用指数反弹来优雅地处理 429 个( 利率限制) 响应 。

下载文件也需要一些清理。 归档. org 添加工具栏脚本, 并在所捕捉的 HTML 中重写 URL。 下载器将所有内容删掉 :

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;
}

regex 模式控点 :

  • <!-- BEGIN WAYBACK TOOLBAR INSERT -->...<!-- END WAYBACK TOOLBAR INSERT --> - 工具栏 HTML
  • <script> 标签标签参考 playback.archive.org
  • 存档元数据评论
  • URL 前缀等 URL 前缀 https://web.archive.org/web/20040527/ 进入所有链接的预览

第3阶段:内容提取噩梦

记得我提到我的博客改变了三次结构吗?

主要采掘使用 CSS 选择器 :

{
  "ContentSelector": "div.post"
}

但这里有个有趣的怪异 在我的旧网站的版本里 div.post 曾经在 <form> 元素。 代码必须在删除不需要的元素之前提取内容, 否则要删除 <form> 将实际的博客内容炸为核弹:

// 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);

缩略 ExtractMainContent 方法使用等级搜索查找内容 :

// 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));

如果主选项失败, 此工具还有后退选择器 :

  1. div.blogpost, div.singlepost, article
  2. #content, #main-content, #PostBody
  3. .post-content, .entry-content, .article-content
  4. 最后,只有 <body> 如果所有其他都失败

然后有很长的元素清单 来剥离在Techter内容提取之后的元素:

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

第4阶段:第4阶段:标记生成

一旦我们有干净的 HTML 内容, 反反向向向上下负向 处理将其转换为 GitHub-flavered Markdown 的重型升降机。

但输出需要一些后处理 。 旧的 HTML 往往有奇怪的缩进, 会混淆 Markdown 分析器( 缩进的行会变成代码块 ! ) 。 因此有清理 :

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

最后的输出包括我的博客的正面事项格式:

# Article Title




Article content here...

第5阶段:LLM 授权标签生成

有趣的是,旧的博客文章往往没有标签,或者连我目前的网站结构都没有意义。所以我整合了Ollama来分析内容和生成相关标签。

配置是直截了当的:

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

我用的是 gemma3:4b 低温 (0.3) 使输出保持一致 — — 我们不想在标签上出现创造性的幻觉。 注意; 对于我的博客来说,这个功能与文章短短一样有效,如果你的博客更能看得更久的话,可以看出与模型上下文窗口相匹配的块状和总结技术。

更长期员额

以下是一个实际的限制:LLMs有上下文窗口, 将整个博客文章放入其中以生成标签是浪费的。 工具将内容解压缩到 3,000 个字符 :

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

对于标签生成, 最初的 3000 个字符通常包含足够的上下文, 以了解该文章的内容。 即时指示模型以特定技术类别为重点 :

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

回应分析是防御性的 — — 如果Ollama退回垃圾或时数, 我们只需要一个空标签清单,

采掘日期:多战略办法

寻找原始出版日期是令人惊讶的难题。 我的旧博客多年来将日期储存在不同地方。 工具尝试多种策略:

  1. 已配置的选择器 (例如, .postfoot)
  2. 元元标签: article:published_time, DC.date.issued
  3. HTML5 <time> 元素元素
  4. 共同日期班级: .date, .post-date, .entry-date
  5. Regex 模式 在原始 HTML 上( ISO 格式、 斜线分隔等)
  6. 后退:档案快照日期本身

特别令人烦恼的是,我的旧博客模板“在2004年5月27日,

管道管弦

最酷的建筑比特是下载和转换如何平行使用.NET 频道:

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

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

这意味着转换从第一个文件下载开始, 而不是等待所有下载完成。 约束容量( 10 项) 提供回压 - 如果转换落后, 下载速度会放慢以匹配 。

限制和困难

让我们诚实地说,这个工具不能做什么:

  1. 与我的博客非常具体 - 选择器、图案和日期提取都按大多数lucid.co.uk调制。你需要定制不同网站的所有内容。

  2. org没有全部档案 - 有些页面没有存档, 或档案中CSS/图像被损坏。

  3. 图像是最佳效果 - 工具试图下载图像 从回背机, 但很多只是永远消失。

  4. 各地断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断的断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断断 从2004年起, 外部链接指向已不存在的站点。 我正研究一个单独的解决方案(自动存档. org 链接替换在中间软件中- 博客文章即将发布! ) 。

  5. LLM 标签不完善 - Ollama制成的标签通常合理,但有时误标。建议进行手动审查。

  6. CDX API 缩短 - 对于有数千页的网址,CDX API可能会返回被截断的结果。代码优雅地处理,但你可能会错过一些页面。

运行中

如果您想调整此选项以适应您自己的网站( 需要自定义) , 命令是 :

# 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

该工具支持优雅的关闭( Ctrl+C) , 并且可以从剩余部分恢复, 因为文件是本地缓存 。

结果

在我的旧博客上发表这篇文章后, 2004年1月1日 2004年1月1日 之前! 阅读它们是一段有趣的历程。 在 jQuery 存在之前的网络开发讨论。 有关现在完全过时的技术的文章。 作为年轻开发者,我持有一些尴尬的观点。

您可使用以下工具查找所有导入的柱子 : 已进口 类别标签 。

下一个是什么

进口内容有很多死线 — — 这只是20年网络内容的本质。 构建中间软件解决方案 并且:

  1. 为旧的 URL 检测404 秒
  2. 自动找到最接近的归档. org 的快照
  3. 重定向或显示存档版本

包包到上

建立这个工具是一个周末项目, 它变成了真正有用的东西。 如果您从旧的博客中丢失了内容, 档案馆. org 就有一个很好的机会拥有它。 如果您对 C# 感到满意, 这里的技术( CDX API 查询、 HTML 内容提取、 Markdown 一代、 LLM 标记) 可以适应您自己的恢复项目 。

代码在 Github.com/scottgal/ mostlylylucid. 核植物包装这不是一个光滑的图书馆-- 它是一个针对我具体情况的 专门设计的工具-- 但它可能会给大家 提供自己档案冒险的想法。

说真的 去捐给档案室 org 他们正在做重要的工作

Finding related posts...
logo

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