GEOGenerative Engine Optimization生成式引擎优化关心的是一篇内容能不能被 AI 搜索、AI 问答顺利读到、拆开并引用。我在给树成林AI营相关的问答内容写稿、做发布前自测时用的就是下面这套方法先用两个开源工具离线打分再用自己写的规则脚本补上它们照顾不到的地方。本文所有命令和输出都是 2026年10月21日在一台 Linux 机器上重新跑出来的Python 3.13.5两个工具都装在独立的虚拟环境里。检测对象是一段自己写的示例文章主题是 Python 虚拟环境怎么选和任何机构无关。一、准备环境两个工具都已经发布到 PyPI可以直接 pip 安装mkdircsdn_democdcsdn_demo python3-mvenv venv venv/bin/pipinstallgeo-optimizer-skill venv/bin/pipinstallchinese-geo markdown安装完成后的版本$ venv/bin/pip show geo-optimizer-skill chinese-geo | grep -E Name|Version|License Name: geo-optimizer-skill Version: 4.19.5 License: MIT Name: Chinese-Geo Version: 0.3.0 License: MITgeo-optimizer-skill 的源码在 GitHub 的 auriti-labs/geo-optimizer-skillChinese-Geo 在 qingqingpi/Chinese-Geo。装之前建议先把源码包下载下来翻一遍确认没有安装钩子和多余的网络请求这两个包我都看过。二、准备检测样本示例文章写了两个版本内容相同只是格式不同结构版 sample_structured.md有 H2 小标题、一张对比表和一个“常见问题”小节纯文本版 sample_plain.txt去掉小标题和表格只剩段落模拟头条、抖音图文这类不支持标题层级的平台。结构版的开头是这样的# Python 虚拟环境怎么选venv、conda 和 uv 的区别 结论先说只写纯 Python 项目用自带的 venv 就够了需要装 CUDA、科学计算这类带二进制依赖的包conda 更省事想要更快的安装速度和锁文件可以试试 uv。 ## venv 是什么 venv 是 Python 3.3 起自带的标准库模块不用额外安装。……两个工具都按网页来分析所以先把 Markdown 转成 HTML。纯文本版只生成p段落# md2html.pyimportsys,re,markdowndefto_html(path,plainFalse):textopen(path,encodingutf-8).read().strip()title,bodytext.split(\n,1)titletitle.lstrip(# ).strip()ifplain:# 纯文本平台只有段落没有标题层级和表格paras[p.strip()forpinre.split(r\n\s*\n,body)ifp.strip()]inner.join(fp{p}/pforpinparas)else:innermarkdown.markdown(body,extensions[tables])return(f!doctype htmlhtml langzh-CNheadmeta charsetutf-8ftitle{title}/title/headbodyarticleh1{title}/h1f{inner}/article/body/html)if__name____main__:src,dstsys.argv,sys.argvopen(dst,w,encodingutf-8).write(to_html(src,plainsrc.endswith(.txt)))mkdirsite venv/bin/python md2html.py sample_structured.md site/structured.html venv/bin/python md2html.py sample_plain.txt site/plain.html三、先踩一个坑命令行只接受公网 URL两个工具的命令行入口都是给已上线网站用的。我用python -m http.server在本机起了一个服务直接把本机地址交给它们两个都拒绝了$ venv/bin/geo --lang en audit --url http://127.0.0.1:8765/structured.html --format text Note: --langen accepted. Full CLI localization is planned for a future release; output is currently in English regardless of this flag. ❌ Unsafe URL: URL points to a non-public address. Please use a public URL (e.g., https://example.com). $ venv/bin/chinese-geo structure http://127.0.0.1:8765/structured.html 无法获取页面 HTMLblocked or unresolvable host (SSRF guard)。先确认 URL 可访问再重试。这是两边都做了 SSRF 防护是合理的设计。但对还没发布的稿子来说命令行用不了只能绕开网络层直接调用它们的 Python 分析函数。这样做也有好处完全离线稿子不会发到任何地方。四、离线调用两个工具的分析函数# check.pyimportsysfrombs4importBeautifulSoupfromgeo_optimizer.core.citabilityimportaudit_citabilityfromseogeo.domimportscanfromseogeo.rules.baseimportAuditContextfromseogeo.rules.contentimportcheck_content_structurefromseogeo.structure_signalsimportanalyze_structureforpathinsys.argv[1:]:htmlopen(path,encodingutf-8).read()# 1) geo-optimizer-skill可引用性检测传入 BeautifulSoup 对象离线raudit_citability(BeautifulSoup(html,html.parser),https://example.invalid/)# 2) Chinese-Geo内容结构规则 结构信号ctxAuditContext(urlhttps://example.invalid/,htmlhtml)ctx.domscan(html)ccheck_content_structure(ctx)stanalyze_structure(html)print(f{path})print(fgeo-optimizer 可引用性:{r.total_score}/100 等级:{r.grade})print( 前三建议:,r.top_improvements[:3])print(fChinese-Geo 内容结构:{c.score}/{c.max_score}状态:{c.status})print( 说明:,c.message)print( 胶囊段:,st[capsule])URL 参数只是占位用的是保留域名 example.invalid不会真的去访问。运行结果$ venv/bin/python check.py site/plain.html site/structured.html site/plain.html geo-optimizer 可引用性: 26/100 等级: critical 前三建议: [Add attributed quotes in blockquote (41% AI visibility), Include quantitative data: percentages, figures, metrics (33%), Improve fluency with longer paragraphs and logical connectives (29%)] Chinese-Geo 内容结构: 8/16 状态: warn 说明: 内容结构待改进2/4 项信号 胶囊段: {paragraphs: 6, well_sized: 6, too_long: 0, note: 答案胶囊字数为经验范围约 40–150 字、非硬标准结论先行的短段更易被 AI 抽取引用。} site/structured.html geo-optimizer 可引用性: 28/100 等级: critical 前三建议: [Add attributed quotes in blockquote (41% AI visibility), Include quantitative data: percentages, figures, metrics (33%), Improve fluency with longer paragraphs and logical connectives (29%)] Chinese-Geo 内容结构: 16/16 状态: pass 说明: 内容结构良好4/4 项可引用性信号 胶囊段: {paragraphs: 6, well_sized: 6, too_long: 0, note: 答案胶囊字数为经验范围约 40–150 字、非硬标准结论先行的短段更易被 AI 抽取引用。}同一篇内容加上小标题和表格之后Chinese-Geo 从 8/16 变成 16/16geo-optimizer-skill 只从 26 涨到 28两版都是 critical。为什么差这么多要看两个工具各自在量什么。五、geo-optimizer-skill 在量什么audit_citability 一共跑 47 项检测每项有自己的满分。总分是各项得分之和除以各项满分之和再乘以 100。“前三建议”取的是没有检测到的项目按预设的影响大小排序。等级划分写在源码_compute_grade里86 分及以上 excellent68 分及以上 good36 分及以上 foundation其余是 critical。把每一项打印出来frombs4importBeautifulSoupfromgeo_optimizer.core.citabilityimportaudit_citability raudit_citability(BeautifulSoup(open(site/plain.html).read(),html.parser),https://example.invalid/)forminr.methods:print(f{m.name}:{m.score}/{m.max_score}{m.detected})纯文本版的部分输出quotation_addition: 0/6 False statistics_addition: 0/6 False fluency_optimization: 2/6 False cite_sources: 0/6 False answer_first: 0/5 False passage_density: 0/5 False technical_terms: 5/5 True authoritative_tone: 0/5 False easy_to_understand: 3/5 True unique_words: 3/3 True keyword_stuffing: 6/6 False readability: 5/8 True faq_in_content: 0/6 False …… eeat_signals: 0/7 False …… crawl_budget: 3/3 True answer_capsule: 0/4 False我按用途把这 47 项大致分成几类类别代表检测项看什么引用与证据quotation_addition、cite_sources、statistics_addition、attribution_completeness有没有带出处的引语、来源、统计数字表达方式fluency_optimization、answer_first、authoritative_tone、definition_patterns段落长度、连接词、每节开头是否先给事实结构faq_in_content、format_mix、comparison_content、snippet_ready问答、列表表格、对比内容可信度eeat_signals、first_party_data、social_proof作者信息、一手数据站点与商业shopping_readiness、conversion_funnel、international_geo电商、多语言站点相关信号如果对公网站点跑完整的geo audit它还会按 robots、llms.txt、schema、meta 等类别算一个站点总分。源码里第 2 版评分的各类满分是CATEGORY_MAX_V2{google_ai:20,robots:14,schema:14,content:14,brand_entity:12,meta:11,llms:6,signals:6,ai_discovery:3,}内容本身只占其中 14 分。文章发在第三方平台上robots、schema、llms.txt 这些都由平台决定作者改不了。六、Chinese-Geo 在量什么Chinese-Geo 的check_content_structure满分 16只看 4 个信号源码很短signals{single_h1:bool(d)andd.headings[h1]1,extractable_sections:has_h2orhas_faq,# H2 小节 或 FAQPage 问答都是可抽取分节enough_text:bool(d)andd.text_lengthMIN_CHARS,# MIN_CHARS 300has_list_or_table:bool(d)and(d.has_listord.has_table),}4 项全中是 pass中 2 到 3 项是 warn更少是 fail。纯文本版有唯一 H1、正文也超过 300 字但没有 H2也没有列表和表格所以只中 2 项拿 8/16。analyze_structure不打分只统计“答案胶囊”每段 40 到 150 字算适中。工具自己的说明也写了这是经验范围不是硬标准。它还带一个零网络的演示命令能看到完整体检的 7 个维度$ venv/bin/chinese-geo demo # chinese-geo demo —— 内置 fixture 站体检 → 修复 → 复检 …… **修复前 36/100待打基础 → 修复后 100/100优秀 Δ 64** ## 分项前后对比 | 维度 | 修复前 | 修复后 | |---|---|---| | ★国内 AI 爬虫准入 | 3/26 | 26/26 ⬆ | | 内容可引用性 | 4/24 | 24/24 ⬆ | | AI 可发现性 | 0/8 | 8/8 ⬆ | | 技术基线 | 19/26 | 26/26 ⬆ | | 结构化 | 3/22 | 22/22 ⬆ | | 海外 AI 爬虫准入 | 12/12 | 12/12 | | JS 渲染可见性 | 7/14 | 14/14 ⬆ |和 geo-optimizer-skill 一样大部分分数落在爬虫准入、技术基线、结构化数据这些站点层面的项目上单篇平台文章能直接影响的主要是“内容可引用性”。七、用在中文稿子上的局限翻源码能找到几处中文吃亏的地方。其一geo-optimizer-skill 用空格分词。fluency_optimization 里计算段落长度的代码是para_lengths[len(p.get_text().split())forpinparagraphsifp.get_text().strip()]中文句子里空格很少所以一个上百字的段落也只算几个“词”。结构版前 6 段算出来是而“平均段长 ≥30 词”才能拿满这一项的段长分中文正文几乎达不到。其二连接词只认英文和意大利文。源码注释写的是# Logical connectives (EN IT)列表里是 therefore、however、quindi、inoltre 这类词“因此”“但是”“另外”都不算。其三可读性按 Flesch-Kincaid 公式算要数英文音节用在中文上没有意义。answer_first 判断每节开头是否先给事实用的正则除了认两位以上的数字和百分比认的是 is、are、can 这类英文断言词和几个意大利文动词。其四纯文本平台的结构分基本是定值。只要平台不支持小标题和列表Chinese-Geo 的内容结构就停在 8/16怎么改写都上不去geo-optimizer-skill 里 FAQ、表格、对比这几项也同样拿不到分。其五站点层面的检测项不适用。Schema、robots、llms.txt、E-E-A-T 署名在平台上发帖时作者都控制不了。所以我的用法是只拿分数做同一篇稿子不同版本之间的横向对比看改动是变好还是变差不拿绝对分数去和英文网站比也不为了凑某一项分数去加和内容无关的引语或数字。八、自己写一个规则脚本现成工具不检查的东西比如联系方式、价格和报名类词语、绝对化用语或者一篇对比文里几个对象的篇幅是否大致对等可以自己写几十行正则来查。下面是简化版把检测对象换成了示例文章里的三个工具名# rule_check.pyimportre,sys BRANDS{venv:rvenv,conda:rconda,uv:r\buv\b}CONTACTr微信|加群|私信|二维码|https?://|报名|优惠|\d\s*元ABSOLUTEr最好|第一|唯一|100%|保证|绝对|稳赚defcheck(path):linesopen(path,encodingutf-8).read().strip().split(\n)title,bodylines[0].lstrip(# ).strip(),\n.join(lines[1:])paras[pforpinre.split(r\n\s*\n,body)ifp.strip()]totalsum(len(p)forpinparas)or1report{标题:title}# 1. 每个名称在正文出现几次、提到它的段落占全文多少forname,patinBRANDS.items():hit[pforpinparasifre.search(pat,p)]report[name]f{len(re.findall(pat,body))}次 / 篇幅{sum(map(len,hit))/total:.0%}# 2. 联系方式、价格、报名类词report[引流词]re.findall(CONTACT,body)# 3. 绝对化用语report[绝对化]re.findall(ABSOLUTE,body)# 4. 超过 150 字的长段按字符数不按空格分词report[超长段][len(p)forpinparasiflen(p)150andnotp.startswith(|)]returnreportforfinsys.argv[1:]:fork,vincheck(f).items():print(f{k}:{v})对示例文章运行$ python3 rule_check.py sample_structured.md 标题: Python 虚拟环境怎么选venv、conda 和 uv 的区别 venv: 9次 / 篇幅73% conda: 7次 / 篇幅61% uv: 6次 / 篇幅49% 引流词: [] 绝对化: [] 超长段: []再拿一句故意写坏的话测一下$ printf # 测试\n\nuv 是最好的包管理工具想要配置模板可以私信我。\n bad.md $ python3 rule_check.py bad.md 标题: 测试 venv: 0次 / 篇幅0% conda: 0次 / 篇幅0% uv: 1次 / 篇幅100% 引流词: [私信] 绝对化: [最好] 超长段: []篇幅这一项是按“提到该名称的段落字数占全文的比例”来算的。一段话同时提到几个名称就会重复计入所以几项加起来会超过 100%它只适合比较几个对象之间的相对差距。我实际用的版本在此基础上多加了几条规则标题里是否只出现单一名称、名称和价格类词是否出现在同一行、某个对象的篇幅是否明显超过其他对象。规则按自己的需要增减就行。九、小结两个工具都能 pip 安装、离线调用命令行只接受公网 URL未发布的稿子要走 Python 函数。geo-optimizer-skill 的 47 项检测按英文网页设计中文稿分数普遍偏低只适合做版本之间的横向对比。Chinese-Geo 的内容结构检测只有 4 个信号对中文友好但纯文本平台的结构分会固定在 8/16。现成工具不查的东西比如引流词、绝对化用语、篇幅是否对等用几十行正则就能补上。