Back to "我的旧博客用档案库@. @org 和大量 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

我的旧博客用档案库@. @org 和大量 C#_#来重现我的老部落格

Monday, 24 November 2025

所以,你可能已经注意到数百个 @"_new"}博客文章 我终于建立了一个工具, 用来从数字墓地中拯救我的内容。 这是我在[email protected] @._uk#.的旧博客

为何归档@. @org绝对辉煌?

在我潜入技术领域之前 我必须先大呼小叫 互联网归档 这个非营利组织自“1996,”以来一直悄悄地将网络归档, 保存数十亿个否则会永远丢失的网页@.}

想想看,你写在“2005,”中的每一篇博客文章。 每个地理城市页面都写了“MS K2”,每个我的空间简介“-”都有一个很好的机会通过档案馆(Calabication)<.>@org_.}他们基本上经营着整个互联网的博物馆,}由捐款和赠款资助的「.」

当我的旧主机提供商因为我像SMART那样 失踪了(和我的备份 因为我以为所有的内容都永远消失了 .

如果你从未向它们捐赠过, 请考虑这样做。 他们保存了我们共同的数字历史。

问题@: @我的博客一团糟

@.}显然我至少换了三次博客设置,

  1. 早日 @ (2004) @: 一些主机 ASP=.NET的东西,内容包裹在 <div class="post"> 内有一个 <form> 元素“(”因为当时一切都是表单
  2. 中中期不同的模板结构 @,}日期在不同的地方
  3. 后来年份@: 又一次改组,选择者稍有不同

从记忆中它使用了一些自定义的东西 子图文 @(Phil Haack'}部落格主題@).}依據社群伺服器{(}(a) 线人 ASP=.NET 用于主机站点 @,}由前ASP@,#NET PM Rob Howard)}♪.

这意味着任何提取工具必须足够灵活, 才能处理多个 HTML 结构@ . @ a\ MS K1one 大小符合所有 @ "}\ scrapper wasQ'} t to cut it @ MPK4}

输入归档Org进口器

我建造的 归档导入器 解决这个非常特殊的问题@. @ it'}这是一个“._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_'%s CDX API 以查找所有我的博客“.”的存档快照。 此 API 返回了包含时间戳@ , MIME type @ MS K2 和 HTTP 状态代码@ MPK3

// 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 模式过滤 URLs @ . 我的旧日志遵循了此模式 /posts/[number].aspx{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}所以

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

这样我只能抓取真实的博客poss@,}而不是档案页面 @,}分类页面,}或RSS feedQ.}

阶段2: 做一个有利率限制的好公民

org 是一个公共事业单位 他们有Google或Amazon的基建预算 所以下载者故意保守:

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

这表示下载上百个文章需要一段时间., 但是这代表了做.的正确选择。 工具也处理着“ MSK4” 429 和 “ MS K5” 限制@)”) 用指数反弹优雅地回应了“.”

下载文件需要清理@. @Aglication_.org, 添加工具栏脚本并重写 HTML @.}在所捕捉的HTML#MSK3 下载机条中包含所有%:}

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 前缀等 https://web.archive.org/web/20040527/ 进入所有链接的预览

“内容提取噩梦”阶段

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

主要采掘使用 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> 如果所有其他都失败

然后' 长长的元素列表 从内容提取后剥离出来:

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

阶段 *4: 标记生成

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

但输出需要一些后端的“-”处理@.}旧 HTML通常有奇怪的缩进, 这会混淆Markdown 解析器 @(}缩进的线条成为代码块{!).} 所以这里是‘'’s cleanup_:}

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

最后的输出包括我的博客' @s front matter格式@:

# Article Title




Article content here...

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

现在,对于有趣的部分“.” 旧博客文章通常没有标签@,或标记,

配置是直截了当的@: @%

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

我用的是 gemma3:4b 低温 @(0.3) 保持输出一致性@–}我们不想要在标签中出现创造性的幻觉,

更长期员额

这里的' 是一个实际的限制@:LMs有上下文窗口 @,,

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

对于标签元件组来说,第一个“,”字符通常包含足够多的上下文来理解该文章的内容@.。 即时指示模型聚焦于ech{-}特定类别 @:}

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

如果 Ollama 返回垃圾或乘数出@,, 我们只需要一个空标签列表,

采掘日期=:}一个多-}战略方法

寻找原始出版日期是令人惊讶的狡猾@. @我的旧博客在过去几年里在不同地方存储了日期_.}这个工具尝试多种策略:

  1. 已配置的选择器 (E.G., .postfoot)
  2. 元元标签: article:published_time, DC.date.issued
  3. HTML5 <time> 元素要素
  4. 共同日期班级: .date, .post-date, .entry-date
  5. Regex 模式 在原始的 HTML 上 @ ( @ ISO 格式@ MS K1 @ slash} @ MPK2 @ sparated_ , @ etc _ .)}
  6. 后退档案快照日期本身

一个特别令人烦恼的格式是我旧的博客模板“' @%s "}张贴在星期四@,May @27,} @#2004 @{11:21P"_字符串}.}上面有<'>的具体解析

管道管弦

最酷的建筑比特是使用“.+NET channels@:”来平行下载和转换如何运行。

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

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

这意味着转换在第一个文件下载@ , @ 而不是等待所有下载完成 .} 连接能力 < MS K2 items\ ) > 如果转换落后于,}下载速度减慢以匹配 提供回压 *\ MPK4}

限制和困难

让我们让' @%s诚实地知道这个工具能用到什么 @ ' @ t doQ:}

  1. 与我的博客非常具体。 @– @% 1 选择器@ ,} 模式 @ MS K2} 日期提取都按大多数时间调整 : mostlucid_ .co @ MPK4uk @ I.} 您需要定制不同站点的所有内容@.}

  2. org does'}没有拥有一切 @– @% 某些页面是'_ t存档@,}或被损坏的 CSS=/#images @MS K4}归档

  3. 图像为最佳@- @effort @-_% 此工具试图从回溯机下载图像@ ,}但许多已永远消失 #.#

  4. 任何地方的死连结 @-_@ 2004} 外部链接指向已不存在的站点@.I'm,

  5. LLM 标签不完善 @–_Ollama-}(OllamaMSK1产生的標籤通常很合情合理) @MS K2}但偶尔会错过 mark@.}手册审查,

  6. CDX API 截断 CDX API 可能会返回截断的结果@. @% 此代码优雅地处理, 但您可能错过一些 pages @.}

运行中

如果您想要调整此选项以适应您自己的站点 @ (it'}需要自定义@ MS K2, 命令是 @ I:}

# 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)}并可以从剩余部分恢复, 因为文件已缓存本地@ MPK3}

结果

在我的旧博客“MSMK0”上播放这篇文章后, 1月 1st, NSK2 @._Posts 有关现已完全过时的技术的文章@.}和一些我以年轻开发者的身份所持有的尴尬看法*#.

您可使用 : 已进口 分类标签@. @%

下一步是什么?

进口内容含有大量死链接@–, 构建中间软件解决方案 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}这

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

正在上打包

建立这个工具是一个周末项目, 它变成了真正有用的@. @ @ 如果您在旧博客“,Q”中丢失了内容的话\ '}(那里)'}档案库{.org有一个不错的机会

代码在 GithubMS K0com/Scottgal}/}大多是平庸的 .Nnuget packages@.@ it' @% 不是一个光滑的图书馆 @ – @ it'} 为我的具体情况而设计的“ MS K4” 工具@- @ but it might give you ideas for your own crigical adventions @. @

认真的去捐给档案馆 他们正在做重要工作

logo

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