StyloBot 发布序列@:StyloExtrap {-} 本地学习 HTML 到 标记转换器 (中文 (Chinese Simplified))

StyloBot 发布序列@:StyloExtrap {-} 本地学习 HTML 到 标记转换器

Tuesday, 23 June 2026

//

13 minute read

StyloBot v8}让一个站点为AI 爬行者提供其本地边端的页面受控的标记下方视图@ ,}在不向 CDN.这篇文章是关于转换“ MS K3” 和“ StyloExtrap” 这个漫步虫的提取器 清晰度 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}和狗粮环圈 {\fnarial black\fs12\bord0\shad0\4aH00\fscy11\fscx90\fscy120\1cH00FFFF\b0}

StyloBot

Stylo Exct Mostlucid.AvaloniaMS K1UI 测试 斯泰罗博特Name 清晰度 最优礼金.Naiad

StyloBot 释放系列

  1. 行为@, @% 不是身份为何StyloBot以行为方式模拟客户?
  2. ASP=.@NET 用户界面@ : 服务器@ MS K1 在检测结果上方的表面
  3. 在LongM-Running .NET服务中查找和固定无约束增长使引擎在生产过程中无趣的可靠性纪律
  4. 檔案型態Script UI: Express, fastifyMS K2 和浏览器组件
  5. 侧车建筑@ : 检测引擎如何连接到非@ MS K1NET 堆栈
  6. 学习加快速度“:”适应性学习系统“, 4 -”记忆和裁决缓存
  7. 静坐不动的测试: 校验纪律 @: 一个 BDF 文件驱动回溯@,load @MS K3和校准
  8. StyloExptracte {-} 本地学习 HTML 到 标记下转换器: HTML→ Markdown 层与探测器对齐 MSSK2 行尸虫清晰识别捕捉了, 和狗食环让它诚实

决定哪个请求得到标记的探测器在 行为@, @% 不是身份-=YTET -伊甸园字幕组=- 翻译: extract-markdown 相同选项 DetectionPolicyMiddleware 包括 侧车建筑“;”的可靠性纪律 防止网关漏出内存,而这是在 寻找和遏制无约束增长资料来源:: GithubMS .com/scottgalMS K2styloExtract (垃圾桶) V1.7.1 错误在 GithubMS .com/scottgalMS K2lucidview.


StyloBot v8 补充什么?

当AI 爬行器击中一条路径时, 操作员标记了 Markdown @ - @ 符合条件@ ,} 网关交换回应 : * 该爬行者从上游页面上方得到的GFM body\ MS K3 * 不带任何chrome, 没有JavaScriptMSQK5 没有任何饼干横幅 MSsk6 上游站点保持未动=. 每一个其他请求 , 搜索引擎\ MPK10} 常规API client mSC11} 继续收到原HTMLZ□.}

当分类器就位后, 形状是显而易见的元件@: 将请求归类为爬行器 @ (\StyloBot 已经这样做了: @),通过内容%-extraction colum_ MS K4 project to MarkdownQ,返回到 HTML=. 探测器管道分类 BotType.AiBot 与所有其他判决一样快速的“-path lantency”, DetectionPolicyMiddleware 在“7.x”中,通过判决命名的行动政策是“vó7 work . 缺失的一块, 以及“vá8 添加了‘, ” 是抽水机本身 @.

Cloudflare 船上的边缘-Side版类似特性MS K1。 如果您拥有边端□. 自行- 托管的 StyloBot 操作员}{'t},,这对执行“克劳德法雷”设置了三个限制: < ' t':}

  1. 这个网站位于StyloBot网关的上游, Cloudflare 能够达到标记点数, 因为它们是边端 @ . @ a StyloBot 网关位于上游源头前, 它不具有'}控制@,}代理 YARP 亚美@._# 内容必须在入口上提取, 不要在源头, 也不要在一些 SaaS 圆- tripMSSK3}上游站点不动@.}
  2. 本地端@. @ no Python @ , @ no nodeQ, @ 没有单独的服务 @ MPK3 @ 网关是单 阿奥特- 已公布的二进制@. 添加 HTML 的 Python 侧车到 Markdown 会击败部署形状 @.
  3. 速度足够快,可以坐在热路上. 如果“"”将标记保存到 AI 爬行器@"}按请求添加“MS K2”%s , 操作员关闭了此选项。预算是用于缓冲卡的 sub-15ms p99,这是现有检测中继器在.内所生活的地方

电线 extract-markdown @"AiBot 的策略*" 是一个配置行: 一个小型的适配器包MS K2Mostlylucid.BotDetection.StyloExtract“)”和“JSON.}六行 JsonsonMSMK1 ”操作员在“,”中将软件包丢掉,添加了规则{,。AI爬行者开始为仍然对人使用 HTML 的相同的 URL 获得标记。

StyloExtract 有三个逃生级别按成本排序 :

  1. 静态提取@. @% 默认路径@. @ passe @ ,} 清除@ MS K2} 分类=,_ walking\ , 将#.Q} 在网关热路上运行, 没有额外的依赖性 .+H handles every SSS services siteks .}
  2. 编剧制作@. @% 可选的套件“.”驱动一个无头铬,用于其可见内容为水化客户端的 SPAS+-}#MSK1侧面页面加载@. 同一下游管道;只是不同的抓取器{.
  3. 操作员模板@. @% 手动逃生舱. 每个敌对主机的 YAML 文件@, 拨号主要content 选择器 @.Hot}-reloaded.

静态路径是生活在热路上的路径@. @ 另两个存在是因为真实的\ -}世界 HTML以两种不同的方式被打破了...: 有些页面需要一个浏览器来转换\ I,},有些页面则需要浏览器去转换\ '}和一些网页 ConáMSK4t 完全遵循任何结构_.{

@ " 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_ , 代码块~, 图像

更难识别的是一个“.” 网络内容提取 既定基准 WWX 预算外我开始阅读时最先进的是一个叫 Python 的工具 轨迹@ . @ 我将负载Q-@ 包含的想法移植到 @ I.NET, 并添加了一层 trafilatura doesZ'}t have:_ 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_-}主机网页,模板相同) <-}这个网站大部分都通过快速路径-}

指纹是 中哈什 常规 DOM-path 代表@, LSH 液 此文章的匹配数学是否与% '/ tmatter有关? 关键在于它能让 per-}#host 学习便宜到可以运行每一个请求@.}

助行器

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

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

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

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

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

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

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

狗食环

StyloExtrap 存在前我所建的横贯-平台 Avalonia 桌面标记查看器@. 最初的目的是为了喂狗 最优礼金.Naiad{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}里面的船 .md @ ,} 以美人鱼支援为原生文件 MS K1} 使它成为本地化@ , Name 当StyloExtraprition developed, reclearVIEW 发展了一个“ MSKO4” 打开网页 page+"} 命令 ({Ctrl+}hiftMS K8W}): 粘贴一个 URLK11process,} 将 HTML 手持到 StyloexplainMSQK13} 并且把任何标记的回传回来的东西都变成".} 没有服务器\ ,} 没有嵌入式浏览器\ k16\ no Chromium@.} 完全提取=-}和MS19render 路径 生活在同一个单个“ MEK20file ex@.} path

清晰的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个文本\ MS K1 @ node @ - @ 白色空格兄弟姐妹 @ MPK3} 四个倒塌的空格@ IMK4 共同马克@'%s 缩放-code- 4个空位的街区规则火灾@.行尸 [Post title](/blog/post) 以四个空格开始的直线上的天体@. @% 记分牌 将整行作为代码块剖析@ . @ 括号文本转换为字面文字@ I. @ 链接已死@ MPK2}

单位测试通过,因为测试显示字符串 [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 这是 Avalonia UI 测试工具的清晰功能, 用于拖动 , 点击 < msk1 鼠标\ 滚动},\ 屏幕截图\ MS K4\ 和脚本播放回放;\ 本文中的每个清晰视频截图都由它“.”捕捉到。 桌面侧面自动=,\ 设置为 StyloExtrap 可以重弹并校验: “ 清晰虚拟” 曝光无需重新@-_ 打开应用程序并按下鼠标Mostlylucid.StyloExtract.Playwright 与测试环“;”无关。它是 JSQ-“正在发送输入 ficker@,”在下面的它自己的章节中所覆盖的JSQ.)

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

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

这对我管用,因为我认为这是闭环 工作流程工作流程 可能没有"'\t generalise@." 本地标记降记模式 它生产 doZ.

如何清晰地将它连接在

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 * +* 清洁者 闪烁角 有趣的代码开始于分隔区@. @%

片段@ . @% 走在身体上 , 沉入任何语义标签\ 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,驱动无头铬通过 lay人赖@,waits for hydation@,}并返回后 post-_JS HTML 到提取器的其余部分 @MS K3}

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站点 并丢弃了提取的'%s输出+.}在结构上合作的半半个新闻"-}新消息 @(BC,}守护者{),}维基百科> ,GitHub repo READMEsMS9GhostMSSK10ZK11s changelogMS K12Hacker News#-} 超脂质分类员发现主内容干净,行车手制作了可读的Markdown}.}每页100至30公斤清洁流

在另一半“-所有鸟类”上 “(}(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

真正的修正是经过训练的模型“.” /Per-元素特性 “(gag 身份”\ ,类 hash桶@-name hash kitbilts @,}文本“MS K6lathMSk},}链接>-cdensity,sibling fage*,siblling 形状 祖先出现=) 变成一个小梯度 <-_boosted分类♪, WWX 预算外 已导出至 ONNX由@._NET通过 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/*,在被送回前由 StyloExtrap 将其响应体从 HTML 转换为 Markdown 。 相同的网关继续将HTML 对其它要求都服务@. 值得在此明确表示 @:StyloBot'}分类器是行为=, not a user#-}代理字符串匹配_.}它抓住诚实的AI机器人宣布自己的名字 和 鬼鬼祟祟地说 行为@, @% 不是身份 对于“).” 或任何一种香味如何得到相同的答案? “:” 一个轻量级的标记下移,而不是完全的 HTML@, CSS @,和JavaScript, 它只会被刮掉。“MS K4 ” 网站作者一直向人类提供HTML服务而不另写一个 Markdown 站点<, 并停止全额支付#- page

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

这里究竟有什么新东西?

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

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

  1. 一个本地运行的分类器, 决定“"” 这是 AI Laper @." @StyloBot.}
  2. 本地运行并将 HTML 转换为可读取的 Markdown @. @StyloExtrap@.}提取器
  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.

Finding related posts...
logo

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