
1. 项目概述当AI遇见无障碍合规审计最近在做一个Web项目上线前被法务和合规部门卡住了要求必须提供一份详尽的WCAGWeb Content Accessibility Guidelines网页内容无障碍指南合规性审计报告。这玩意儿可不是简单跑个自动化工具就能搞定的传统的审计流程要么依赖昂贵的第三方服务要么需要投入大量人力进行手动检查费时费力还容易遗漏细节。就在我头疼的时候突然想到现在AI这么火特别是像Claude这类大语言模型在理解和分析文本、代码方面表现不俗能不能让它来帮我自动化一部分审计工作呢这个想法催生了今天要分享的主题利用Claude进行免费的、AI驱动的WCAG无障碍合规性自动化审计。本质上这不是要完全取代专业的无障碍测试工程师或那些成熟的商业工具如axe、WAVE而是构建一个智能化的辅助工作流。它能帮你快速完成第一轮“粗筛”从海量页面中定位出高概率的合规性问题生成结构化的审计线索从而让专业测试人员可以更聚焦于复杂场景和手动验证极大提升审计效率和覆盖率。对于独立开发者、中小团队或者预算有限但又有合规需求的项目来说这无疑是一个极具性价比的解决方案。2. 核心思路与方案设计2.1 为什么选择Claude而非其他AI市面上AI助手不少为什么偏偏是Claude这背后有几个关键的考量点。首先Claude在长文本处理和理解上具有显著优势其上下文窗口足够大能够一次性吞下整个网页的HTML结构、CSS样式甚至部分JavaScript逻辑片段进行分析。这对于需要全局审视页面结构的无障碍审计至关重要。其次Claude在遵循指令和进行结构化输出方面表现稳定。我们可以通过精心设计的提示词Prompt让它严格按照WCAG 2.1 AA级目前最广泛接受的标准的检查点来逐项审查并以JSON、Markdown表格等格式输出结果方便后续集成到CI/CD流水线或审计管理平台中。注意AI审计不能替代法律意义上的正式合规认证。它生成的报告是“发现问题线索”而非“最终判决”。任何关键的合规结论尤其是涉及法律风险的都必须由人类专家进行复核和确认。与完全依赖规则引擎的传统自动化工具如使用axe-core库相比AI驱动的审计有其独特价值。规则引擎擅长检查那些有明确、可量化标准的问题比如“图片是否有alt属性”、“表单输入框是否有关联的label”。但对于更依赖语义理解和上下文判断的问题AI就显示出优势了。例如检查“alt文本的描述是否准确且传达了与图片相同的功能或信息”、“链接文本是否具有独立于上下文的意义”WCAG 2.4.4链接目的、“页面的标题是否清晰描述了主题或目的”WCAG 2.4.2页面标题这些都需要一定的自然语言理解和逻辑推理能力而这正是大语言模型的强项。2.2 自动化审计工作流蓝图整个自动化审计系统的设计目标是高效、可重复、可集成。我设计的工作流核心分为四个阶段目标获取与预处理这不是简单给个URL让AI去爬。为了提高审计准确性和效率我们需要向AI提供更丰富、更准确的页面信息。最佳实践是使用无头浏览器如Puppeteer、Playwright在真实渲染环境中抓取页面。我们不仅要获取最终的DOM还应捕获完整的HTML源码包括动态生成的内容。计算后的样式信息Computed Styles这对于检查颜色对比度、元素可见性至关重要。无障碍树Accessibility Tree的序列化信息。现代浏览器都提供了通过API如Chrome DevTools Protocol获取无障碍树的能力这直接反映了屏幕阅读器等辅助技术“看到”的页面结构。关键状态的截图。对于颜色对比度等检查虽然AI可以通过色值分析但提供截图作为参考也是好方法。智能分析与提示词工程这是核心环节。我们将预处理后的数据HTML、无障碍树摘要、关键截图描述连同精心编写的提示词一并提交给Claude API。提示词的设计需要包含角色定义明确告诉Claude它现在是一名资深的无障碍合规专家。审计标准明确指定依据WCAG 2.1 AA级别进行审计并可以附上相关成功标准的简要说明或编号。输入数据说明清晰地告诉AI你提供的HTML、无障碍树数据分别是什么应该如何利用。输出格式要求强制要求以结构化格式如JSON输出每个问题必须包含唯一ID、WCAG成功标准编号、问题描述、问题所在的HTML元素选择器或代码片段、严重性等级严重/中等/轻微、修复建议。这是实现自动化的关键。结果解析与报告生成接收Claude返回的结构化数据进行解析和去重。然后可以将结果转换为多种形式的报告例如静态HTML报告可视化展示按严重性、类型分类并可直接链接到问题代码位置。JSON/CSV数据便于导入到项目管理工具如Jira中创建工单。与现有工具集成将AI发现的问题与axe-core等工具的结果进行合并和对比分析提供一个更全面的视图。集成与自动化触发将上述流程脚本化并集成到开发流程中。例如在Git的pre-commit钩子中审计修改过的页面在CI/CD流水线如GitHub Actions, GitLab CI中对每次部署的预览环境进行全站或抽样审计定期对生产环境的关键页面进行巡检。3. 实操搭建从零构建你的AI审计机器人3.1 环境准备与工具链选型工欲善其事必先利其器。我们首先需要搭建一个能够运行自动化脚本的环境。基础环境Node.js环境推荐v18以上这是我们运行脚本的主力。选择Node.js是因为其丰富的生态系统特别是无头浏览器和控制AI API的库非常成熟。Python环境可选3.8以上如果你更熟悉Python可以使用Playwright的Python版本和相应的OpenAI/Anthropic SDK。本文以Node.js为例。核心工具库Playwright我选择Playwright而非Puppeteer因为它对多浏览器Chromium, Firefox, WebKit的支持更好且API设计更现代捕获无障碍树和网络请求等更便捷。安装npm install playwright。Anthropic官方SDK用于调用Claude API。安装npm install anthropic-ai/sdk。你需要提前在Anthropic官网注册并获取API密钥。辅助工具库jsdom用于在Node.js中解析和操作HTML可选fs文件系统模块用于读写报告path路径处理。项目初始化创建一个新的项目目录初始化package.json并安装上述依赖。mkdir ai-wcag-auditor cd ai-wcag-auditor npm init -y npm install playwright anthropic-ai/sdk3.2 核心脚本编写分步解析接下来我们一步步构建核心的audit.js脚本。第一步页面信息抓取器这个函数负责使用Playwright打开页面等待其完全加载包括网络空闲和动态内容然后提取我们需要的数据。const { chromium } require(playwright); async function fetchPageData(url) { const browser await chromium.launch({ headless: true }); // 无头模式运行 const page await browser.newPage(); // 监听并拦截所有请求可以过滤掉图片等大资源以加快速度 await page.route(**/*.{png,jpg,jpeg,svg,gif,woff2}, route route.abort()); console.log(正在导航至: ${url}); await page.goto(url, { waitUntil: networkidle }); // 等待网络空闲 // 提取关键数据 const html await page.content(); const title await page.title(); // 获取计算后的无障碍树信息通过CDP协议 const cdpSession await page.context().newCDPSession(page); const { nodes } await cdpSession.send(Accessibility.getFullAXTree); // 我们将无障碍树简化提取关键属性供AI分析 const axTreeSummary simplifyAXTree(nodes); // 获取首屏截图Base64用于可能的视觉分析 const screenshotBuffer await page.screenshot({ fullPage: false }); const screenshotBase64 screenshotBuffer.toString(base64); await browser.close(); return { url, title, html, // 完整HTML axTreeSummary, // 简化的无障碍树信息 screenshotBase64 // 可选根据API token长度决定是否使用 }; } // 简化无障碍树只保留对审计关键的信息 function simplifyAXTree(nodes) { return nodes.map(node ({ role: node.role?.value, name: node.name?.value, description: node.description?.value, value: node.value?.value, properties: node.properties?.map(p ({ name: p.name, value: p.value })) })).filter(n n.role); // 过滤掉无效节点 }第二步构造AI提示词核心中的核心这是决定审计质量的关键。我们需要给Claude一个清晰、具体、可执行的指令。function constructPrompt(pageData) { // 注意HTML内容很长需要确保不超过Claude模型的上下文限制如Claude 3.5 Sonnet 200K。 // 实践中可以对HTML进行智能裁剪比如只保留body内容或移除脚本和样式内容。 const truncatedHtml pageData.html.substring(0, 150000); // 示例截取前150K字符 const prompt 你是一名专业的Web无障碍合规审计专家专门依据WCAG 2.1 AA级别标准进行评估。 我将提供一个网页的关键信息请你对其进行全面的无障碍合规性审计。 ## 审计对象信息 - 页面标题${pageData.title} - 页面URL${pageData.url} ## 提供的页面数据 1. **HTML结构** (已截断): \\\html ${truncatedHtml} \\\ 2. **无障碍树摘要** (反映了屏幕阅读器可访问的信息): ${JSON.stringify(pageData.axTreeSummary, null, 2)} ## 你的任务 请严格依据WCAG 2.1 AA级别的成功标准检查上述网页数据找出所有可能存在的无障碍合规问题。 ## 输出要求 你必须以纯JSON数组格式输出数组中的每个对象代表一个发现的问题。每个问题对象必须包含以下字段 - \id\: 一个简短的唯一标识符例如 no_alt_text_1。 - \wcagCriterion\: 对应的WCAG 2.1成功标准编号例如 1.1.1。 - \level\: 合规级别固定为 AA。 - \description\: 清晰的问题描述说明哪里不符合标准。 - \element\: 出问题的HTML元素选择器或代码片段尽可能精确。 - \severity\: 严重程度取值为 [Critical, High, Medium, Low]。Critical指完全阻断辅助技术访问High指造成重大理解困难Medium指造成一定困扰Low指轻微瑕疵。 - \recommendation\: 具体的修复建议。 ## 审计重点检查项包括但不限于 - **1.1.1 非文本内容**所有img、svg、area是否有有意义的alt属性装饰性图片是否已设置alt - **1.3.1 信息和关系**标题结构h1-h6是否逻辑清晰列表是否使用正确的ul/ol标签表格是否使用th关联数据单元格 - **1.4.3 对比度最小**文本与背景的颜色对比度是否至少达到4.5:1大文本至少3:1【你可以根据提供的HTML样式信息推断或指出需要工具验证的可疑区域】。 - **2.1.1 键盘**所有交互功能链接、按钮、表单控件是否可以通过键盘Tab键访问焦点指示器是否可见 - **2.4.4 链接目的**链接文本是否独立于上下文即有明确含义避免“点击这里”、“更多”等模糊文本。 - **3.2.1 聚焦时**接收焦点时是否不会引发意外的上下文变化 - **4.1.1 解析**HTML是否语法良好元素嵌套正确标签闭合完整 - **4.1.2 名称、角色、值**自定义UI控件如ARIA组件是否提供了正确的角色role、名称aria-label或aria-labelledby和状态aria-checked, aria-expanded等 现在请开始审计并输出JSON数组。如果未发现问题则输出空数组 []。 ; return prompt; }第三步调用Claude API并解析结果使用Anthropic SDK发送请求并处理返回的JSON数据。const Anthropic require(anthropic-ai/sdk); require(dotenv).config(); // 用于从.env文件加载API密钥 const anthropic new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, // 你的API密钥 }); async function auditWithClaude(prompt) { try { const message await anthropic.messages.create({ model: claude-3-5-sonnet-20241022, // 使用最新版本模型 max_tokens: 4096, temperature: 0.1, // 低温度确保输出稳定、确定性高 messages: [{ role: user, content: prompt }], }); const content message.content[0].text; // 尝试从返回的文本中提取JSON部分 const jsonMatch content.match(/\[\s*\{.*\}\s*\]/s); if (jsonMatch) { return JSON.parse(jsonMatch[0]); } else { console.error(未能从AI响应中解析出JSON。响应内容, content.substring(0, 500)); return []; } } catch (error) { console.error(调用Claude API失败, error); return []; } }第四步生成审计报告将AI返回的结构化问题列表转换成易于阅读和处理的报告。const fs require(fs).promises; const path require(path); async function generateReport(auditResults, pageUrl, outputDir ./reports) { await fs.mkdir(outputDir, { recursive: true }); const timestamp new Date().toISOString().replace(/[:.]/g, -); const filename audit-report-${timestamp}.json; const filepath path.join(outputDir, filename); const report { meta: { url: pageUrl, auditTime: timestamp, standard: WCAG 2.1 AA, tool: Claude AI Auditor }, summary: { totalIssues: auditResults.length, bySeverity: auditResults.reduce((acc, issue) { acc[issue.severity] (acc[issue.severity] || 0) 1; return acc; }, {}), byCriterion: auditResults.reduce((acc, issue) { acc[issue.wcagCriterion] (acc[issue.wcagCriterion] || 0) 1; return acc; }, {}) }, issues: auditResults }; await fs.writeFile(filepath, JSON.stringify(report, null, 2)); console.log(审计报告已生成: ${filepath}); // 同时生成一个简化的HTML报告便于预览 await generateHtmlReport(report, outputDir, timestamp); return report; }第五步主流程串联最后我们编写一个主函数将上述所有步骤串联起来。async function main() { const targetUrl process.argv[2] || https://example.com; // 从命令行参数获取URL if (!targetUrl.startsWith(http)) { console.error(请提供一个有效的URL例如: node audit.js https://your-site.com); process.exit(1); } console.log(开始对 ${targetUrl} 进行WCAG AI审计...); // 1. 抓取页面数据 const pageData await fetchPageData(targetUrl); console.log(页面数据抓取完成。); // 2. 构造提示词 const prompt constructPrompt(pageData); console.log(提示词构造完成长度:, prompt.length); // 3. 调用AI审计 console.log(正在调用Claude API进行分析这可能需要一些时间...); const auditResults await auditWithClaude(prompt); console.log(AI分析完成共发现 ${auditResults.length} 个潜在问题。); // 4. 生成报告 await generateReport(auditResults, targetUrl); // 5. 在控制台简要输出严重问题 const criticalIssues auditResults.filter(i i.severity Critical || i.severity High); if (criticalIssues.length 0) { console.log(\n 严重/高优先级问题摘要 ); criticalIssues.forEach(issue { console.log([${issue.severity}] ${issue.wcagCriterion}: ${issue.description}); console.log( 元素: ${issue.element.substring(0, 100)}...); }); } } if (require.main module) { main().catch(console.error); }现在你可以通过命令行运行这个脚本了node audit.js https://your-website.com。4. 高级技巧与优化策略4.1 提升审计准确性的关键点直接运行上述基础脚本可能会遇到一些问题比如AI“幻觉”生成不存在的问题、对复杂页面分析不全等。通过以下策略可以显著提升准确性1. 分块与聚焦审计对于大型单页应用SPA或内容极其丰富的页面一次性将整个HTML扔给AI效果可能不好。更好的策略是“分而治之”。按组件/区域分块利用Playwright定位到页面主要区域如header、main、footer、特定的div idapp分别提取其内部HTML和无障碍树进行审计。按责任分块将审计任务拆分。第一次调用只检查“语义化结构与标签”如标题、列表、表格。第二次调用专注于“交互与键盘导航”如按钮、链接、表单。第三次调用分析“颜色与对比度”。这样每次提示词更专注AI的产出也更精准。2. 提供“黄金标准”示例在提示词中除了告诉AI“做什么”还可以告诉它“怎么做”和“什么是好的”。提供一两个正面和反面的代码示例。## 审计示例 **反面示例问题** img srclogo.png !-- 违反1.1.1缺少alt文本 -- a href/products点击这里/a !-- 违反2.4.4链接文本不明确 -- **正面示例合规** img srclogo.png altAcme公司主页标志 !-- 提供有意义的alt -- a href/products查看我们的产品列表/a !-- 链接文本自描述 --这能有效对齐AI的判断标准减少误报。3. 结合规则引擎进行验证AI不是万能的将AI审计与传统的规则引擎如axe-core结合能实现优势互补。你可以先运行axe-core进行快速、确定性的检查如属性缺失、ARIA误用然后将axe的结果和页面数据一起喂给Claude让它专注于axe不擅长的语义化判断部分。这样既能保证基础问题不漏检又能利用AI处理复杂场景。4.2 成本控制与性能优化使用Claude API会产生费用虽然比聘请人工审计便宜得多但对于大量页面或频繁扫描成本也需要考虑。智能采样与增量审计不要每次都对全站所有页面进行审计。在CI/CD中可以只审计本次提交修改所影响的页面或者使用工具如sitemap.xml定期对关键用户路径如登录、购买、核心内容页进行审计。缓存与去重对于内容长期不变的页面如“关于我们”审计结果可以缓存一段时间如一周避免重复分析。优化提示词长度这是控制成本最有效的方法。在constructPrompt函数中对HTML进行预处理移除所有script和style标签内容保留标签本身以维持结构压缩空白字符甚至可以只提取body内具有语义的标签如header,main,nav,article,footer,form,img,a,button等丢弃纯装饰性的div和span。这通常能将HTML体积减少50%以上同时不影响AI对无障碍要点的判断。选择合适的模型Claude 3 Haiku模型比Sonnet和Opus更快、更便宜虽然推理能力稍弱但对于许多常规的、模式化的无障碍检查如检查alt属性、标题层级已经足够。你可以用Haiku做初筛再用Sonnet对Haiku标记出的高优先级问题进行深度分析。5. 实战踩坑与问题排查在实际搭建和运行这套系统的过程中我遇到了不少坑这里把典型的几个问题和解决方案记录下来希望能帮你节省时间。问题一AI返回非JSON格式或解析失败。现象Claude的回复开头或结尾有额外的解释性文字导致JSON.parse失败。解决方案在auditWithClaude函数中我们使用了正则表达式/\[\s*\{.*\}\s*\]/s来提取JSON部分这比单纯相信返回的纯文本更健壮。此外可以在提示词最后强烈强调“必须只输出JSON数组不要有任何其他前缀或后缀解释”。如果问题依然存在可以尝试降低temperature参数到0使输出更确定性。问题二审计结果中出现大量“误报”比如AI认为颜色对比度不足但实际测量是足够的。原因AI仅从HTML和内联样式的色值进行判断但实际渲染效果可能受到CSS层叠、父元素背景、伪元素、背景图片等复杂因素的影响。解决方案在提示词中明确AI的局限性。可以这样写“关于颜色对比度1.4.3请仅对明确通过style属性或简单CSS类定义的文本和背景色进行初步判断。如果颜色来自复杂继承、渐变或图片背景请将问题严重性标记为‘Low’并在建议中注明‘需使用开发者工具或专用对比度检测工具如axe DevTools, Colour Contrast Analyser进行手动验证’。” 更好的办法是将对比度检查完全交给本地运行的axe-core只让AI处理语义问题。问题三对于动态生成的内容审计不全。现象页面上的内容由JavaScript异步加载Playwright抓取时可能内容还未完全出现。解决方案在fetchPageData函数的page.goto后增加更智能的等待逻辑。例如等待某个特定元素出现await page.waitForSelector(#dynamic-content, { state: visible, timeout: 10000 });。或者模拟用户交互如点击“加载更多”按钮后再抓取HTML。更彻底的方法是使用Playwright的page.evaluate执行一段脚本主动触发所有可能的动态加载。问题四API调用超时或频率限制。现象审计复杂页面时提示词很长可能导致API响应超时频繁调用触发速率限制。解决方案设置超时和重试在调用SDK时配置合理的超时时间并实现简单的重试逻辑如最多3次指数退避。分批处理如前所述将大页面分块审计每次调用处理一部分降低单次请求的复杂度和token消耗。队列与限流如果要审计大量页面需要自己实现一个简单的任务队列控制并发请求数避免触发API的速率限制。问题五如何将结果整合到现有工作流解决方案生成的标准化JSON报告是核心。你可以编写一个脚本将JSON报告中的Critical和High级别问题自动创建为Jira或GitHub Issues。在CI/CD流水线中设置质量关卡如果发现Critical级别问题多于N个则令流水线失败阻止合并或部署。将报告上传到内部仪表板如用Grafana展示跟踪整个项目的无障碍合规问题趋势。6. 与传统工具链的融合及扩展思路单独使用AI审计是一个很好的起点但将其融入现有的开发者工具链才能发挥最大价值。与IDE集成可以开发一个VS Code或WebStorm插件在开发者编写代码时对当前编辑的HTML/Vue/React组件文件进行“实时AI审计”。插件可以将组件代码片段发送给Claude API或本地运行的轻量模型在侧边栏即时反馈潜在的无障碍问题实现“左移”测试。作为代码审查助手在Git的Pull Request流程中可以添加一个机器人。当PR中包含对HTML、JSX、Vue模板等文件的修改时机器人自动对受影响页面的预览URL运行AI审计并将结果以评论的形式附在PR中提醒审查者关注无障碍合规性。构建综合审计仪表板开发一个内部管理界面定期如每天对生产环境的核心页面列表运行审计聚合AI审计结果、axe-core扫描结果甚至人工测试记录。通过仪表板团队可以一目了然地看到各个页面的合规健康度、问题分布和修复进度。最后需要再次强调的是技术是辅助人的判断和专业知识始终是核心。AI审计报告是一份高效的“问题线索清单”和“学习指南”它不能替代开发者和测试人员对无障碍原则的深入理解。真正的无障碍源自于从设计、开发到测试全流程中对包容性体验的持续关注和投入。这套自动化工具的目的正是为了降低这项工作的启动门槛和重复劳动成本让团队能更专注于解决那些真正需要人类智慧和同理心的问题。