Back to "本地标记模式"

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

Architecture lucidVIEW Markdown StyloBot StyloExtract

本地标记模式

Wednesday, 24 June 2026

Cloudflare'@"Markdown Mode" 给AI爬行者提供干净的文字, 而不是由 HTMLMS K3StyloBot 操作员通过 StyloExtractiMPK4}快速地在StyloBot 网关上本地运行来获得同样的能力 @,能够坐落在热路端\ ,不需对上游站点做任何改动MSKO7这是StylotopleExpain如何插入 StyoloBot},它是如何插入STyloBat{,}什么狗食 通过清晰识别捕捉到#,和什么'仍然破损=.}


我想复制的东西

Cloudflare 上传了一个特写“, ” 如果被识别的AI爬行者要求获得一个页面 “, ” , 边缘为尸体的标记解剖服务, 而不是完整的 HTML. 爬行器得到实际内容而没有任何chrome@, 没有 JavaScript @, 没有一个 cookie 横幅 . 用户“MS K6 {acking网站” 保持同一页“. ’ ” “爬行机” “MSMK8}生活变得轻松点 ” . 云雾风可以收取费用

校对:Soup

StyloBot 操作员的同样能力有三个制约因素,即云层有三种限制因素:

  1. 这个网站位于StyloBot网关的上游, Cloudflare可以达到标记点, 因为它们是边缘的 @.}一个StyloBot网关坐在上游源头前... ...它不代表 YARP=MSK#t control,
  2. 本地端@. @ no Python @ , @ no nodeQ, @ 没有单独的服务 @ MPK3 @ 网关是单一的 AOT- 已公布的二进制 . 添加 HTML 的 Python 侧车到 Markdown 击败部署形状@.
  3. 速度足够快,可以坐在热路上. 如果“"”将标记保存到 AI 爬行器@"}按请求添加“MS K2”%s , 操作员关闭了此选项。预算是用于缓冲卡的 sub-15ms p99,这是现有检测中继器在.内所生活的地方

StyloBot的侧面已经完成了 : 检测管将AI爬行器分类BotType.AiBot@) 和所有其他判决一样快 #-path lantency #.# DetectionPolicyMiddleware 在 @7.#x 发送中, extract-markdown @"AiBot 的策略*缺少的碎片是提取器本身 @.@

与StyloBot's探测器匹配的 HTML@-_to @-}马克唐层Mostlylucid.BotDetection.StyloExtract“) ” 以及点火规则是 JSON.六行的操作员在“,”中丢弃了软件包。

@ " extracte markdown@ MS K1}实际上意味着什么?

如果您读取面值的图解“% ,” , @ " @ convert HTML to Markdown@ MSSK2是一个已解决的问题 ‘ MS K3’ 有几十个图书馆\ .Reality 是它们都退化在真实页面上 因为它们将文档视为平坦的内容, 而该页面则作为范围界定

真实的-world 网页是 @ 80-95%锅炉板_ MS K2你真正想要的那篇文章 在两三个包里生活 <div>两三百. 幼稚的 HTMLMS K1to- Markdown 库转换所有东西 每条 nav link}每条曲棍球横幅的句子\ , 每个脚MS

因此,提取器必须做两个工作\ :

  1. 识别身体@. @% 剖析的 DOM 中哪个子树含有实际内容@,和哪些亚树是chrome?
  2. 将身体... ... 一旦您在“'”中孤立了它, “,” 项目将子树切换到 Markdown, 保护下游阅读器“ @( human 或 LLM) ” 的结构。 它会关注“MS K4 领导层次”, 内线链接@,}列出‘, table_ , 代码块~, 图像

更难识别的是一个“.” 网络内容提取 设定的基准是 WWXB.}我刚开始阅读时的艺术状态 是一个叫做 Python 工具叫 TrafilaturaMS K1}我把负载的“-”想法移植到 @.NET, 并添加了一层 trifilatura does't has : per-_host 模板学习 通过结构指纹 .

形状是:

parse HTML → clean → fingerprint the structure → does this fingerprint
  match a template I've seen on this host before?
    yes → apply the cached extractor → render
    no  → run the heuristic classifier → induce a fresh extractor →
          cache it under this host's fingerprint → render

网关第一次看到主机的页面@,}它支付全部超常=-}分类器成本 为中页 @(~200}每个来自主机的结构指纹匹配者获得缓存提取器后的每一页 ).}这是少数 CSS-}选择者的查询 {(~30s}).}(Same_-}主机网页,模板相同) <-}这个网站大部分都通过快速路径-}

指纹是MinHash的草图, 是正常的 DOM-path submation@,}上面有一个 LSH 带子, 上面写着"-millisecond 探针"\ .}匹配数学与这篇文章“'”无关

助行器

翻转的一面是狗食圈让我赚到它的地方

StyloExptrate 第一版通过行走分类区块和投射而排放的马克唐 element.TextContent.Trim() 输出中“%.”每个区块都成为段落 “.” 每个标题都变成 # text 无论是H1还是 HMS K1 anchors 都倒在光滑的文字上 . Lists 失去了他们的子弹*.}代码区块

这是严格意义上的“" Markdown ." ” 它“'”也没用 “. ” 避免解析铬@ , @ 和我们手持一面段落的墙, 其中唯一的信号是偶发的平原@ MS K1} text noun sings .} 服务于马克唐的整点在于此结构包含信息 *\ .} 解开该结构, 而您'} 刚刚给爬行器一个小一点的字符串包 .}

所以下一个版本的StyloExtract 将每个分类内容块的 DOM 移动到DOM 并发布真实的 GFM:

  • <h1> 中经 <h6> 透过#6成为 @1 # 字符字符字符
  • <a href> 成为 [text](href)
  • <em><strong> 保持其重点
  • <code> 保持反向, <pre> 变成一堵栅栏, language-x 横穿
  • <ul><ol> 发布真实的子弹和编号列表
  • <blockquote> 每个行的前缀 > “(”和多“-”段引号 > body\n>\n> body 《公约》
  • <table> 当源码太复杂, 无法让 GFM 表达 &(multi-Row thead=,}嵌入的表格@,块内容时返回原始 HTML 。 @ /}
  • 图像成像 ![alt](src) 或单独插入 <figure>

校对@(}首个切口是 @304QZK6 @MS K7QKB 用于表格的“-+Heavy page”=)}它位于 “~70QQS @Z/QQQMS12KB最差的情况 @MSC13}*完整提取管道的交接份额从‘25-55%QQForth =#5-11%.}

助行器也是第一次破碎的部分

狗食环

清晰的VIEW 是一个与 StyloExtrapt.}我一起建造的标记查看器。 这个产品是一个浏览器@ -}端阅读器, 它使用 URL_,}获取它\ ,}在响应中运行Styloextram {,} 并显示由此生成的 Markdown MSKO5} 使用选项是 @"}I want to read a long connection on a flown continution without the JavaScripptMSSK8}或仅仅因为原始页面有 eye=- leeped CSSMS K10} 执行系统是在服务器上的 StylotExtraint *, • 一个小型的标记转换器 在浏览器,}

清晰的VEW给了我一个狗食环,上面有牙牙.}其他StyloBot发布的文章 - 系列文章提到仪表板是喂养狗的表面*; *这在协议层是真的 我,我@ . @ I'#m 在圆圈里 @ I.}IMS K3}会原谅许多怪异的输出 只要底线对齐的话

清晰度使下游读者的标记为“(@me,}但读内容 <%).}It>'}与AI爬行者使用箱子的形状相同 物质“,”不是作为仪器“.” ,当输出出错时您会立即看到它‘,’ 在 '} @ k5 _ 提取器生成 X"}和{">I 正在读 X."}之间没有抽象的层

于是我打开清晰的视野, 指着我自己的博客Index.}卡片代表着. 然后我就滚动"MSSK2" [Post title](/blog/post) {-} 字括号文字\ -} 而不是样式化的可点击链接@.

单位“ -” 测试套件是绿色的“ I.” 为缩进 HTML @ MS K4} passes@ .}内写为“ MPK3” 附加器的 meture I'd [Post title](/blog/post). 标记反正是错误的 @.

没有测试的错误类不会被捕获

博客索引是用 Ladywind@.}尾风输出为可读性缩进{:每个折叠式 div 会比其父/ .} 更进一步地坐上两个空格。 当您到达一个部落格“ MSMK3}卡通链接” ,}(源 HTML 看起来像 @: ) 的实际锁定时,

<section class="...">
    <div class="container...">
        <div class="grid...">
            <div class="card...">
                <a href="/blog/post-a">Post title</a>
                ...

漫步者@' @s text_-}处理助手 @, AppendEscapedInline, 折叠空格运行到一个单独的空间@. 在其中的一个调用中, 这是正确的 @:此函数维持着 a prevWs 禁止连续的白色空格的旗子在调用@,}旗号 resets @.}所以当行者访问连续的文本时 -node-}of{-}{白人空格兄弟姐妹\ MPK6}这正是缩进的 HTML 在空内线元素之间产生的 {-}每通电话都发出一个倒塌的主要空间

四个缩放包包@, @ 4个文本 @ - @ node @ MPK2 @ 白色空格兄弟姐妹@ MS K3 @ 四个已倒塌的空格 @ IMK4 @ 普通 MarkQ'}% 缩放的马卡-# code\ - @ 区块规则在四个空格中的火灾@ MOK8 @ 漫步器 @ MAK9 @ [Post title](/blog/post) 以四个空格开始的线条上的 . Markdig 将整行作为代码块.\ _ 括号文本转换为字面文字@.}链接是 dead @.}

单位测试通过,因为测试显示字符串 [Post title](/blog/post) 在输出中的某处显示“. ” 它确实“MS K1 ” It “' ” 就在代码块内, 现在“MSC3 ”

修正为两行@ :, 在线上 @ MS K1}\ start , prime prevWs = true 自动 头一 每个文本节点中的主要空白会被跳过, 而不是被排放的 @ . 缩放的 HTML 内的主要空白永远不会达到输出@ MS K1 inner- 段落仍然会倒塌到单个空格@ MPK3

有趣的是测试结果 应: 平面=.}-文本 .Contains() 检查 字符字符字符 它们是在错误的普通马克区块类型@.}我需要的是 结构性结构 plament : @ 剖析行走器@'}输出为实实在在的 PublicMark Mark 采集器,并声明段落是 special MSSK2}链接 为 Link{,}没有虚假代码块 .}Markdig'}AST gave you that for free_.}所以用回归测试来进行错误修正 =, 和回归试验以 lint useing_MS K8}一个小助手 使用任何行进器输出,}将其与 MarkdiggQ,}和President:}

  • 除非源头是栅栏块,否则无缩排代码区块
  • 源 HTML 中每个链接都以真实身份存在 LinkInline 《阿ST》内
  • 围栏的-区数与宣布的期望相符

为了证明 Lint 有牙齿\ ,} 我恢复了原来的修正并运行 lint 套件@.}(完全一个测试失败) “- ” 就是使用 4\ MOSK3\ nested- wrapper 形状“. ” 的测试 。

该单项检查现在贯穿于套件“.”中每个行尸测试,同一类的未来回归在结构上被抓住 “, ”而不是通过字符串匹配“MS K2 ”来抓取。 这意味着I'在CI里会找到它们,而不是在清晰的VIEW. \ }

在V1.7.1walker fix:每个部落格-page卡的解析, 以其摘要作为合适的段落MS K4而不是代码块内的括号{-} text@.}为真正的可点击链接。

狗食实际上需要什么

在每件产品中, 单位测试是绿色的, 演示效果和操作员设置了正确的配置标记, 然后您发出一个版本, 一天后用户打开了一个问题, 说 @"This doesZ't 工作在真实内容上@."}每个产品都点击这个#.。 诚实的回答是测试装置和显示内容从某种意义上来说都是无菌的:

狗食环是这个陷阱中最便宜的出路。 “"”这一短语被使用得非常松散,“"”指的是某种特定的东西。 单独产品@, 与另外的用户@, 碰巧消耗其产品表面的 StyloExptracl' @%s 输出@ . @ @ 如果清晰可见显示已破损的Markdown@,}( 清晰的VEW) @'}用户抱怨有清晰性 @ MPK3 。 在单独的问题追踪器中,

如果清晰度是StyloExtraptestlease metuture@, @I'}它写成不育的内容 因为我知道提取者喜欢什么 因为清晰度存在于自己的世界, 它指向我的博客“, ” 用尾风, 来生成缩记的HTML形状,触发了错误等级@MS K7}用该产品作为用户的五分钟内出现的虫

许多 v1.7.x 的释放可追溯到此循环 .} 结构化\ MPK2\ walker 输出@ MS K3v1.7.0)} 因为 StyloExtrapt 第一版无法读取 styloEW}'}当STyloExplain 正在发送平坦段落\ .} 领先的 @ - whitespace fix 因为后端风站点明显破了 post+-行器版本\ I. • 输出=-}质量 Lint 套件, 因为我想要下一个臭虫类是 CISK13\ caughtMS K14}

本篇文章的贡献是命名它@:}构建一个 消费品消费产品 与您平行 基础设施建设产品“, ” 通过消费者消费您自己的基础设施。“. 基础设施层的错误率下降为消费面值=. 班级 基础设施层的覆盖面会随着所有您想为“.” 写一个测试的消费者通知而扩大。

跨越堆叠的闭环环

StyloExptract {/} 清晰的VEW是我在每一个项目中运行的模式的一个实例。 这个循环是:}

flowchart LR
    PB[visible product<br/>behaviour] --> TR[test/review<br/>loop]
    TR --> AP[architectural<br/>primitive]
    AP --> RL[reusable<br/>library]
    RL --> WE[written<br/>explanation]
    WE --> LG[LLM-readable<br/>grammar]
    LG --> NP[next<br/>product]
    NP --> PB

产品中的臭虫表面@. 修补成为结构性主张 @( 测试/review liol ). 这个说法变成了原始的, 其他事物都可以使用. 原始变成一个库MS K5 图书馆可以写到 <.>

此生成的“ , ” 的依附圖, 在 I 运行的工程中, 此圖產生了 “ MS K0 」 , 看上去像“ I: ”

flowchart TB
    LV[lucidVIEW<br/>Avalonia markdown reader]
    SB[StyloBot<br/>detection gateway]
    SF[StyloFlow<br/>policy + flow runtime]
    SE[StyloExtract<br/>HTML → Markdown]
    NA[mostlylucid.Naiad<br/>Mermaid renderer fork]
    DA[mostlylucid.dagre<br/>graph layout]
    EP[mostlylucid.ephemeral<br/>signal + sketch primitives]
    UT[Mostlylucid.Avalonia.UITesting<br/>Avalonia UI test framework]

    SB --> SF
    SB --> SE
    LV --> SE
    LV --> NA
    NA --> DA
    SE --> EP
    SF --> EP
    LV -.tests via.-> UT

Mostlylucid.Avalonia.UITesting 关闭桌面侧面的等效环@. @StyloExtrap.}Playwright 在无头- @web side @.}相同模式{,}不同的表面_:}一个测试MS K6#Aautomation 工具让代理循环能够实际验证它应该修复.}的产品行为

这个交易是真实的 .BARBAR_这个图是乱伦.}一个错误在 mostlylucid.ephemeral 通过StyloExtrapt 和 StyloFlow 连接斯提洛博特和清晰的VIEW. 缓解是时间@-_boxed 释放 @(no 地物 color=,}当版本船舶声称有“)}”时,该版本的船将具有它自己的测试套件.}好处在于我可以在一周内对所有这些船都进行检测 并且它们之间的环境切换成本保持低Q,}因为每层都有相同的形状 : • 一个原始的,}一个图书馆\MS K10 解释 ,\ a pencient.}

也意味着撰写此篇文章是“' @t 是航运StyloExtrap}-}的侧面效果 ” 。 写作 IS 是一个阶段 “. ” 把设计外部化为散文,关闭了由“MS K4”博客卡开始的循环,在LinderVIEW_"}中造成错误,最后与“"”结尾 StyloEXT的下一个消费者拥有一个结构性滑动助手和一个有文件证明的漫步者合同@."

这对我管用,因为我认为这是关闭循环 . 它可能不会是't generalise.

如何清晰地将它连接在

flowchart LR
    URL[URL bar] --> Fetch[HttpClient GET<br/>Accept: text/markdown, text/html]
    Fetch --> Sniff{Content-Type}
    Sniff -->|text/markdown| Render[LiveMarkdown.Avalonia]
    Sniff -->|text/html| Convert[HtmlToMarkdownService]
    Convert --> Sparse{< 200 chars +<br/>SPA markers?}
    Sparse -->|yes| Stub[Stub: needs JS,<br/>open in browser?]
    Sparse -->|no| Render
    Stub --> Render

四个套件引用和一个服务@: @%

public sealed class HtmlToMarkdownService
{
    private readonly IHtmlDomParser _parser = new AngleSharpHtmlDomParser();
    private readonly IDomCleaner _cleaner = new DomCleaner();
    private readonly IBlockSegmenter _segmenter = new BlockSegmenter();
    private readonly IBlockClassifier _classifier =
        HeuristicBlockClassifier.LoadFromEmbeddedResources();
    private readonly IMarkdownRenderer _renderer = new TypedMarkdownRenderer();

    public string Convert(string html, Uri? sourceUri = null)
    {
        var doc = _parser.Parse(html, sourceUri);
        _cleaner.Clean(doc);
        var blocks = _classifier.Classify(_segmenter.Segment(doc));
        return _renderer.Render(blocks, ExtractionProfile.RagFull);
    }
}

/}转换为 @/}SPA stub)}所以当有问题时,用户可以指向右边的层 =.}

维基百科:'#Markdown文章通过StyloExtrap}:#标题等级完整*, 内线链接 live@,}代码样本保存=.}

每一阶段的输油管,

flowchart LR
    HTML[HTML] --> P[AngleSharpHtmlDomParser]
    P --> C[DomCleaner<br/>strip script/style]
    C --> S[BlockSegmenter<br/>candidate subtrees]
    S --> K[HeuristicBlockClassifier<br/>role + score]
    K --> W[DomMarkdownWalker<br/>GFM per block]
    W --> R[TypedMarkdownRenderer<br/>profile gate]
    R --> MD[Markdown]

Parser {+} 清除器是 AngleSharp 包件}.} 有趣的代码起始于分割区@ .

片段@ . @% 走在身体上 , 沉入任何语义标签\ MS K1main/article/section/h1-h6/ul/pre/...)+任何 <div>/<section> {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}其他的都太小了

public IReadOnlyList<IElement> Segment(IDocument document)
{
    if (document.Body is null) return Array.Empty<IElement>();
    var result = new List<IElement>();
    Walk(document.Body, result);
    return result;
}

private static void Walk(IElement element, List<IElement> sink)
{
    if (SemanticTags.Contains(element.TagName))   sink.Add(element);
    else if (IsBlockyDiv(element))                sink.Add(element);
    foreach (var child in element.Children) Walk(child, sink);
}

分类器@. @% 每个候选人的得分@, @ 选择非# - @ 重叠获胜者 @ MS K2 @ 标签加 BlockRole (MainContent,标题@,导航=,BoterplateMS K4重复项目}{,}#...).每个被选中的區塊 都能讓它的 DOM 步入结构化的 Markdown:

foreach (var element in selected)
{
    var role = ClassifyRole(element);
    yield return new ExtractedBlock
    {
        Role     = role,
        Text     = element.TextContent.Trim(),
        Markdown = ShouldRenderMarkdown(role) ? DomMarkdownWalker.Render(element) : "",
        Links    = ExtractLinks(element),
        XPath    = XPathBuilder.For(element),
        // ...
    };
}

沃克・. 一个字符串编织机 , *一个DOM通行证 . <a> 中, v1.7.1}bug lived\ :

case "a":
    var href = el.GetAttribute("href") ?? "";
    if (href.Length == 0) { WriteInlineChildren(dest, el); return; }
    dest.Append('[');
    WriteInlineChildren(dest, el);
    dest.Append("](").Append(href).Append(')');
    return;

{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}在 AppendEscapedInline将领先的白空格输入 dest 在此案件之前, 请提前四个空格 [ 使通用马克将线条分析为代码块@.) @%

调试器. 由剖析档显示的门@. @% RagFull 保留文章“-context @(Breadcrumb,相关链接})和落色的铬@(Footer}MS K5头条{,Cookie Banner},Nav_). MainContentOnly 只要保持身体 . AgentNavigation 仅保留 nav @ @ for crap * -#link discover * 仅保存导航@ MS K2}

return p switch
{
    ExtractionProfile.RagFull => b.Role is not (BlockRole.Footer or BlockRole.Header
        or BlockRole.Advertisement or BlockRole.CookieBanner or BlockRole.Boilerplate
        or BlockRole.Unknown or BlockRole.PrimaryNavigation or BlockRole.SecondaryNavigation),
    ExtractionProfile.MainContentOnly => b.Role is BlockRole.MainContent or BlockRole.Article
        or BlockRole.Heading or BlockRole.Summary or BlockRole.Table or BlockRole.CodeBlock
        or BlockRole.RepeatedItem,
    ExtractionProfile.AgentNavigation => b.Role is BlockRole.PrimaryNavigation
        or BlockRole.SecondaryNavigation or BlockRole.Breadcrumb or BlockRole.Form,
    _ => true
};

JSQ- 的 Playwright 播放页面

StyloExtracti's heuristic 运行于静态 HTML 服务器返回@., 即#'}对苏维埃社会主义共和国的站点处以罚款 @(Wikipedia,GitHubMS K5大多数新闻文章 URL=).它打破在SPA外壳上可见内容为水化客户端@MSKO7>除了JSON blobMPK8】 __NEXT_DATA__, __NUXT__, __APOLLO_STATE__静态的 HTML 有元标签 @+}一个骨架 , 而且分类器没有机构可以找到. *

Mostlylucid.StyloExtract.Playwright 管道上游的插头. IRenderedHtmlFetcher“,”驱动无头铬通过Playwright @,}等待水合=,, 并返回“-+JS HTML”后到提取器的其余部分@:}

public async Task<RenderedHtmlResult> FetchAsync(
    Uri uri, RenderOptions? options = null, CancellationToken cancellationToken = default)
{
    var page = await _context.NewPageAsync();
    await page.GotoAsync(uri.ToString(), new PageGotoOptions
    {
        WaitUntil = WaitUntilState.NetworkIdle,
        Timeout = options?.NavigationTimeoutMs ?? 15000,
    });
    var html = await page.ContentAsync();
    await page.CloseAsync();
    return new RenderedHtmlResult { Html = html, FinalUrl = page.Url };
}

唯一的区别是,输入的HTML现在包含JS生产的水合 DOM(日本联合材料制成)“.”

flowchart LR
    URL[URL] --> Choice{Render mode}
    Choice -->|static| HTTP[HttpClient]
    Choice -->|js-required| PW[PlaywrightHtmlFetcher<br/>headless Chromium]
    HTTP --> Pipeline[parse → clean → segment<br/>→ classify → walk → render]
    PW --> Pipeline
    Pipeline --> MD[Markdown]

当操作员运行 StyloExtrapt 服务器@-side 而一个无头浏览器是一个合理的依赖性.}CLI 将两个二进制为此分割=:} stylo-extract @(_AOT} , MS K2MB,}静态- 仅管)和 stylo-extract-playwright (~120MB 曾经是玩家游戏机的 '}浏览器背包落下 @, JSQ-可容纳@).

明晰的维吾尔不使用它 Guntling Playwright 将无头浏览器放入一个没有头部的应用程序中。 下面描述的 SPA stubb 是来自LarryVIEW@MSKZK7s spective_MSSK8}用户所需的正确回应,请告诉用户页面需要一个浏览器“,}把它交给他们”." 一个服务器 “-” StyloBot 操作员没有任何限制和好处

其它动物食狗的外表

四个非“-bugs ” 的元件, 这些元件组成了清晰维尤'}%s fail * -mode management * MPK3

  • 驱动 v1.7.0.的特性 第一栋建筑排放的平面段落 (element.TextContent.Trim() 维基百科是无法读取的 @,}博客卡片失去了所有锁定@.}而不是%"}让它更好 我写的#" docs/styloextract-markdown-spec.md 计算缺少的: 标题水平@ , 线性运行}MS K2 列表 @ , GFM table_ MS K4 块状图像 , 加上四个复制器 URLs. 在 vMS k8 中结构化的\ MSKO7行者工作

  • SPA页 #. bbc.com/news 是下一个“. @js:}恒定 HTML 是元标记 {+} a __NEXT_DATA__ JSON blob 水溶液由JS.StyloExtract正确返回 @~1char, 因为这里没有body{'}#.ClearVIEW 现在嗅到已知框架标记@(}__NEXT_DATA__, __NUXT__, __APOLLO_STATE__, data-reactroot, ng-version=, __REMIX_DATA__“)”和“,}关于稀释输出的 +标记, 使一个小块 : *" @% 此页面使用 @ MS K1_ framework @ MPK2} 清晰的 ViEW 不运行 JavaScript@.} 在浏览器中打开@ ?" ** BBC+M'文章 URLs @Q(/news/articles/<id>{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}真正的服务 <main> 并转换为 Cleanly.主页 @ /文章不对称@ MS K2 而非转换器故障@ I.

    快速装入 bbc@ @ com @ /} MS K2 偵測 Next @ MPK3 @ js@ ,} 產生一個可以解釋客戶端的 stub {-side 翻譯是'} 支援, 並提供開啟的MS K7_ MS8}K8browser handoff.}狀態列顯示警告@ MASK10\ triangle source k11mmode 图标, 加上「 MSC12client MS13} sideside 已建立% ,} 沒有可能的轉換 *"}標籤@.}

  • 语义@- @free page_. example.com 没有无 <main># , 否# <article>@._Heuristic 正确返回无值@.}同样的刺流顺着它.}

  • 校对:-#but@-_无用 @. @'%s 分类过滤器 <select><option>漫步者发现没有 <a href>@, 将选项文本作为段落发送@:} (1)+ACP A(1)+AAI#(69)..."+AXAAN ASHK6 USGK3+ZMK4AAP= Appican MASSK5_BARBAR_.+NET@(41)QQQ} I404Qs MPK4_ANDA AMK5安非他命* 正确的“(”选项是 @'}t link@),但视觉太差了#.可以探测到未来的漫步者通行证 <select> 并发布定义列表或 [42 categories] 简表.

再加上一个抵制明显捷径.的护栏。 当提取量少时,诱惑是“"”回到Jina阅读器@/ r.}jinaMS K4ai / Trafilatura ."LinderVIEW 通过第三个<->读取者使读者隐私泄漏了\□; –每个網址用户访问通过其他操作员 <%'>日志*.}下游链保持本地: 直接标记{,}然后通过STyloExtrat},> 然后是一个元数据库 <meta> / og: 标签@ ,} 然后在浏览器中打开 * MS K2\ \ 每一步种子 Stylo Exct 从同一来源@ , @ 或从我们已有的数据中获取不同的抓取 .} 或合成 {"} 答案是'_ t转换\ "} 从来没有 { "} 使用另一个转换器% MS K6}

专横的--地点覆盖面差距

狗食循环的优点在于 在井上发现断裂输出... ...在'-#_formated pages" .}它不擅长什么?

我有一个烟雾-runner 现在收集了十多个真实的 -world站点 并倾弃了抽取的'}输出*.}在结构合作半部新闻“-”上

在另一半“-所有鸟类”上 “(}(Spopified) ),Notion'}销售网页“MS K4}任何用自定义的尾风组件库建立的东西 ” @-}分类者发现 什么都没有@ ._ Zero mainContent blocks@.}每个候选人都被降级到锅炉板, 因为页面使用%'# t <main><article> 和类名@' @t 匹配框架中的任何模式 -} content 提示 JSON.}

在 JSON 文件上添加更多条目是显而易见的移动@ . @ it' @ squatus also hack\ mskK2 @ a @ MSMK3mole}.}每个主题商店船舶的新类名称\ MS K5} 每一个发布版本都更改了它们 *._ 校正每个 CMS 主题列表 MPK7}s class= @-_ national Convention is a full\ mSSK9

真正的修正是经过培训的模型“MSMK0” “Per-”功能, 它是一个小梯度“-”“boosted分类r”“MS13”功能。 Microsoft.ML.OnnxRuntime. 每个候选人的 45- 功能矢量 MS K2 NSK3 每元素的推论@, @ @~5MB 模型文件,AOT-clean}.

此设计在 StyloExtram repo {(} 中进行。docs/ml-classifier-v2-design.mdI25MBONNX 运行时本地二进制的操作器问题 @'}%s部署@,或将 ML作为单独的可选包保留为操作员选择加入?"(Option_-}回答是FOSC套件生态系统的正确答案=,}但是它的意思是默认情况下是'}, 这意味着大多数操作员都赢了'}这表示大部分生产负荷都是超自然载

在此期间,“,”操作员得到的是 手工手工艺手册 YAML 模板@,}(每个主机 1个文件) , 解析 AOT-k4cleen, h热MS K6 覆盖该主机的上传管道.操作员通知 weird-shopify-tenant.com 產出空 Markdown@,寫入 5 -line YAML 文件, 表示 < " > 代表此主機@ MS K3 mainContent .product-description-body",掉进去了 config/templates/“,”和运行时通过文件系统监测器在秒内通过“System Guatcher”,“.” template add/list/show/remove/test-=YTET -伊甸园字幕组=- 翻译: GET/PUT/DELETE/POST 在公关审查期间,自动安全检查在REST端点发现路径穿行和SERF, 并且那些已经固定了;}测试项目中两条生命的回归套件=.}

操作员模板是地板@.}ML模式是天花板 @.}事实上,在诚实的#-}这两者之间有差距

本系列的“2”部分是 ML 建设+-_Out@.} 由训练的分类师处理真正乱七八糟的 HTML @(_Spopify 主题@,}#Notion 营销页面,}尾风部分库没有语句锚 *)} <main># , 否# <article>,沒有一致的類別@-name signal @,, 並且沒有明顯的超級標籤位址@MS K3v2是"。

船舶的所在地

StyloExtract 以一套相关包件NuGet 为主 : @:Bimactivies@,Heuristics,指印Q,Core},Markdown,AspNetCole}AspNetCoreMSSK6CLI 船舶为主 stylo-extract (OOT, NSK2MB 單一二進位MS K3和 stylo-extract-playwright @ ( @ with headless@ MS K1_ browser refack for JS- presented SPAS}).}当前版本是 @1.7.1.}

StyloBot号综合船舶作为 Mostlylucid.BotDetection.StyloExtract将它添加到网关是两行 Program.cs 和一条规则在 appsettings.json:

{
  "BotDetection": {
    "DetectionPolicies": {
      "Rules": [
        {
          "Name": "ai-bot-docs-markdown",
          "Path": "/docs/*",
          "Types": ["AiBot"],
          "Confidence": ">= 0.85",
          "Action": "extract-markdown"
        }
      ]
    }
  },
  "StyloExtract": {
    "Actions": {
      "extract-markdown": {
        "Profile": "RagFull",
        "Cache": {
          "Mode": "Override",
          "MaxAge": 3600,
          "VaryByBotType": true
        }
      }
    }
  }
}

这上面写着“MSMK0” 任何要求检测器分类为 A AI Bot,}至少有信心的 ASMK2在 /docs/*,在被送回前由 StyloExtrampt 将其响应体从 HTML 转换为 Markdown 。 相同的网关继续为其他请求提供HTML@. 爬行者要求的 MarkDown, 它是一个爬行器, 在用户@-agent @.中大声叫喊着自己。

.}它运行在您已有的同一个网关框上。 此分类器是 StyloBot.}(此解析器是StyloExtrapleMS K8}) 这整件事情都符合 AOT=-所公布的二进制文件 docker run 独自离开 @.

这里究竟有什么新东西?

Cloudflare 号船是一个捆绑的:}它们的分类器“(”是专有的), 摘取器“(” 或相似的叉子{),} 规则:- 评估表层@( 他们的仪表板>),}和边缘+-

与自创-主机网关,相同的能力是四件不同的东西,

  1. 一个本地运行的分类器, 决定“"” 这是 AI Laper @." @StyloBot.}
  2. 本地操作并将 HTML 转换为读器的提取器@ - @ label Markdown @ MS K1}% StyloExtraple.}
  3. 规则=-\评价表面,用来绘制对行动的判断结果_.} DetectionPolicyMiddleware 在斯泰洛博特的 @7._x#.}
  4. 他们都用.运行的基底 不论你的YARP网关在什么盒子里

Cloudflare拥有所有四个“.” 自动- 托管运营商拥有最多三个 “(” , 基底是他们的, 其余是'FOSC). 。

此篇文章之所以存在, 是因为该分解的第二和第三块 - 提取器和规则表面 @ - {'} 在我开始MS K3时, 它们有一个一致的地方故事}它们现在做.

“2”部分涵盖乱七八糟的 ML 分类器“-”HTML尾巴“.”部分,当有'Qs的东西显示‘.’时,它就上船。


Stylo 扩展源@: @% github.com/scottgal/styloextractStyloBot集成包 住在Styloboot重播中 Mostlylucid.BotDetection.StyloExtract. 智能来源 MS K1 github.com/scottgal/lucidview. 关闭 v1.7.1臭虫圈的通用马克输出@ MS K1}质量 Lint helper tests/StyloExtract.Heuristics.Tests/MarkdownOutputLint.cs.

logo

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