如何判断ChatGPT的DOM突变完成?实现完整响应捕获
解决ChatGPT流式响应加载完成后再提取文本的问题
ChatGPT采用流式输出响应,你的MutationObserver会在内容逐步加载时多次触发,导致只能捕获部分文本。要等到完整响应加载完成,关键是识别响应生成结束的DOM标志。
核心思路
ChatGPT的对话项在生成响应时,会带有特定状态标识:
- 正在生成的对话项会包含
generating类(可通过元素审查确认); - 生成过程中会显示"停止生成"按钮(类名通常为
btn-stop),生成完成后该按钮消失。
我们可以通过监听这些状态变化,在响应完全生成后再提取完整文本。
修改后的代码
function handleMutations(mutationsList, observer) { for (const mutation of mutationsList) { if (mutation.type === 'childList') { const markdownElements = document.querySelectorAll('.markdown'); markdownElements.forEach(markdownEl => { // 定位当前markdown所在的对话项容器 const conversationItem = markdownEl.closest('[data-testid="conversation-turn"]'); if (!conversationItem) return; // 检查是否仍在生成响应 const isGenerating = conversationItem.classList.contains('generating') || conversationItem.querySelector('.btn-stop') !== null; // 生成完成后提取完整文本 if (!isGenerating) { const paragraphNodes = markdownEl.querySelectorAll('p'); let fullText = ''; paragraphNodes.forEach(p => { fullText += p.textContent + '\n'; }); console.log('完整响应文本:', fullText); // 可选:若只需处理一次,可在此断开观察者或标记已处理 // observer.disconnect(); } }); } } } const observerConfig = { childList: true, subtree: true }; const observer = new MutationObserver(handleMutations); observer.observe(document.body, observerConfig);
代码说明
- 定位对话容器:通过
closest('[data-testid="conversation-turn"]')找到.markdown所在的完整对话项,确保判断的是当前响应的生成状态。 - 判断生成状态:通过
generating类和btn-stop元素的存在与否,确定响应是否还在流式输出。 - 提取完整文本:生成完成后,遍历所有
<p>元素拼接完整内容,再执行打印或后续语音转换操作。
补充提示
- 若ChatGPT的DOM类名更新,需重新通过元素审查确认
generating类、btn-stop类或对话项的data-testid是否变化。 - 要避免重复处理同一对话项,可给已处理的对话项添加自定义类(如
processed),后续判断时跳过已标记元素。
内容的提问来源于stack exchange,提问作者taylon
相关产品推荐
相关产品推荐

