news 2026/9/27 20:43:00

词达人答题脚本技术解析:DOM解析与混合路线实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
词达人答题脚本技术解析:DOM解析与混合路线实战

1. 词达人答题场景的真实痛点与脚本介入的边界

词达人这类词汇训练工具,本质上是一个“题库匹配 + 选项判定”的交互流程。每次答题,界面会呈现一个英文单词和四个中文释义选项,用户需要在限定时间内点击正确的那一个。对于日常需要刷大量词汇任务的人来说,重复性的点击操作既枯燥又耗时,尤其是当任务量累积到几百上千题的时候,手动完成几乎是一种折磨。这也是为什么“词达人脚本”这个关键词会反复出现在各类技术社区的搜索记录里——大家想要的其实很简单:让机器替自己完成那些机械的、有明确判定逻辑的重复操作。

但这里必须先说清楚一件事:脚本能做的事情,和很多人想象的不太一样。它并不是“破解”或者“绕过”什么,而是模拟人在界面上的正常操作——读取当前题目、匹配答案、点击正确选项、等待下一题加载。整个过程依赖的是对页面结构的解析和对交互节奏的模拟,本质上和你自己用手点没有区别,只是速度快了很多、不需要人盯着。理解这一点很重要,因为它决定了后续所有技术方案的选型方向。

从技术实现的角度看,词达人答题脚本的核心难点集中在三个地方:第一是题目识别,你得知道当前屏幕上显示的是哪个单词;第二是答案匹配,你得有一个可靠的词库或者查询机制来找到正确释义;第三是操作模拟,你得让点击动作被页面正常接收,而不是被判定为异常行为。这三个环节环环相扣,任何一个出问题都会导致脚本失效。

我在实际折腾这类脚本的过程中,踩过的坑远比想象中多。最开始想得很简单——不就是截屏识别文字然后查词典吗?结果发现页面上的文字是动态渲染的,截屏识别的准确率受字体、分辨率、背景色影响极大。后来又尝试直接读取页面DOM结构,这才发现题目和选项都是通过前端框架动态生成的,元素的选择器会随着版本更新而变化。再后来解决了识别问题,又遇到了点击无效的情况——明明坐标算对了,点击事件也发出去了,但页面就是没反应。这些问题一个一个解决下来,才慢慢摸清了这类脚本的完整技术链路。

注意:本文讨论的所有技术方案仅用于个人学习和技术研究,实际使用时应遵守平台的使用条款和相关规定。脚本的本质是自动化工具,它的合理性取决于使用场景和方式。

适合阅读这篇内容的人,大概分三类:一是对浏览器自动化感兴趣、想拿一个真实场景练手的技术爱好者;二是需要批量完成词汇任务、想了解自动化可行性的普通用户;三是对脚本原理好奇、想知道“自动答题”到底是怎么实现的读者。不管你是哪一类,接下来的内容都会从原理到实操、从选型到避坑,把这条链路完整地讲清楚。

2. 三种技术路线的选型对比与最终决策依据

在动手写代码之前,最重要的一步是确定技术路线。词达人答题脚本的实现方式不止一种,每种路线都有各自的适用场景和局限性。我前后尝试过三种方案,下面把它们的优缺点和实际表现逐一拆解,方便你根据自己的情况做选择。

2.1 方案一:图像识别路线(截屏 + OCR + 坐标点击)

这是最容易想到的方案,也是很多新手的第一选择。基本思路是:定时截取屏幕画面,用OCR(光学字符识别)提取题目和选项文字,在本地词库中查找匹配项,然后计算出正确选项的屏幕坐标,模拟鼠标点击。

这个方案最大的优点是通用性强——它不依赖页面的具体实现,只要能截屏和点击,理论上任何界面都能操作。但缺点同样明显:OCR的识别准确率受太多因素影响。词达人页面上的单词字体较小,选项文字有时会有特殊排版,加上背景色和动画效果,OCR经常把“abandon”识别成“aband0n”,把“放弃”识别成“放弁”。一旦识别出错,后续的匹配和点击就全错了。

另一个问题是速度瓶颈。截屏、OCR识别、词库查询、坐标计算、模拟点击,这一套流程走下来,即使优化得再好,每道题也需要1到2秒。如果题目有倒计时限制,这个速度在某些情况下会来不及。而且OCR引擎本身会占用不少系统资源,长时间运行容易导致页面卡顿。

我实测下来的感受是:图像识别路线适合作为兜底方案,但不太适合作为主力方案。它的维护成本也高——页面布局一变,坐标就要重新校准。

2.2 方案二:DOM解析路线(读取页面元素 + 直接操作)

这个方案的核心思路是绕过视觉层面,直接和页面的DOM结构打交道。通过浏览器开发者工具分析页面,找到题目元素和选项元素的选择器,然后用JavaScript读取文本内容、匹配答案、触发点击事件。

相比图像识别,DOM解析的准确率有质的提升——文字是直接从页面读取的,不存在识别错误的问题。速度也快得多,一次完整的读取-匹配-点击循环可以控制在200毫秒以内。而且它不依赖屏幕分辨率和窗口位置,只要页面加载完成就能工作。

但这条路线的门槛在于选择器的稳定性。词达人的前端页面会不定期更新,每次更新都可能导致类名、ID或DOM结构发生变化。我遇到过最夸张的一次,更新后所有选项的类名从“option-item”变成了“answer-choice”,之前写的选择器全部失效。所以用这条路线的話,必须做好选择器的容错设计,比如用多个备选选择器、用文本内容定位而非类名定位等。

另外,DOM解析路线通常需要在浏览器环境中注入脚本,这就涉及到脚本的加载方式和管理问题。后面会详细讲几种注入方式的对比。

2.3 方案三:混合路线(DOM为主 + 图像为辅)

这是我在实际使用中最终采用的方案。核心逻辑是:优先用DOM解析获取题目和选项,如果DOM读取失败(比如页面结构变了、元素还没加载出来),则自动降级到图像识别作为兜底。这样既保证了正常情况下速度和准确率,又在异常情况下有一定的容错能力。

混合路线的实现复杂度比单一方案高,需要维护两套识别逻辑和一套切换机制。但从稳定性角度看,这个投入是值得的。我自己的脚本在连续运行几个小时的情况下,混合路线的成功率能保持在95%以上,而纯DOM路线在页面更新后会直接归零,纯图像路线的成功率则一直在70%到85%之间波动。

下面这张表是我对三种方案的实际对比,数据来自我自己的测试环境:

对比维度图像识别路线DOM解析路线混合路线
识别准确率70%-85%98%以上95%以上
单题耗时1-2秒200毫秒以内300毫秒以内
维护成本中(需校准坐标)高(需跟进页面更新)中高
抗页面更新能力强弱中
实现复杂度低中高
资源占用高低中

选型建议很直接:如果你只是想快速跑通一个能用的版本,图像识别路线入门最快;如果你追求效率和准确率,并且愿意花时间维护选择器,DOM解析路线是首选;如果你需要长时间稳定运行,混合路线最靠谱。

3. DOM解析路线的完整实现链路

确定了技术路线之后,接下来把DOM解析方案的每个环节拆开来讲。这部分是整篇内容的核心,我会尽量把每一步的操作意图和背后的逻辑都说清楚,方便你复现和调整。

3.1 页面结构分析:找到题目和选项的“锚点”

第一步永远是打开浏览器的开发者工具(F12),切到Elements面板,仔细观察答题页面的DOM结构。你需要找到四个关键信息:题目文本所在的元素、四个选项各自的元素、选项的点击触发方式、以及“下一题”按钮的出现时机。

以我分析过的页面为例,题目通常包裹在一个带有特定类名的容器里,比如<div class="question-title">abandon</div>,四个选项则是<div class="option-item">放弃</div>这样的结构。但要注意,这些类名不是固定的,不同版本可能不同。所以我在实际脚本中不会硬编码类名,而是用更灵活的方式定位。

我的做法是:先通过文本特征找到题目元素。比如题目通常是一个英文单词,可以用正则表达式/^[a-zA-Z]+$/来匹配。选项则是包含中文文本的可点击元素。这样即使类名变了,只要页面结构没有根本性变化,脚本仍然能工作。

// 用文本特征定位题目元素,而非依赖类名 function findQuestionElement() { const allDivs = document.querySelectorAll('div, span, p'); for (const el of allDivs) { const text = el.textContent.trim(); // 题目通常是纯英文单词,长度在2-20之间 if (/^[a-zA-Z]{2,20}$/.test(text) && el.children.length === 0) { return el; } } return null; }

这段代码的逻辑是遍历页面上所有可能的文本容器,找到第一个符合“纯英文单词”特征的叶子节点。这种方式的鲁棒性比直接查类名好很多,代价是遍历会稍微耗时一点,但在实际测试中影响可以忽略。

3.2 词库的构建与匹配策略

识别出题目单词之后,下一步是找到对应的中文释义。这里有两种思路:一是本地词库,二是在线查询。

本地词库的方案是提前准备一个单词-释义的映射表,可以用JSON格式存储,脚本运行时直接查表。优点是速度快、不依赖网络;缺点是词库覆盖面有限,遇到生僻词就查不到。我的做法是先用一个基础词库(比如四六级核心词汇)打底,然后对查不到的单词做记录,后续手动补充。

在线查询的方案是调用翻译API或者爬取在线词典页面。优点是覆盖面广,缺点是速度慢、可能被限流。我一般把在线查询作为兜底,只在本地词库匹配失败时才触发。

匹配策略上有一个细节值得注意:词达人的选项顺序是打乱的,所以不能简单地取第一个选项。正确的做法是把题目单词查到的释义和四个选项逐一比对,找到匹配度最高的那个。比对时要注意同义词和近义词的情况,比如“abandon”的释义可能是“放弃”也可能是“抛弃”,如果选项里出现的是“抛弃”,简单的字符串相等判断就会失败。

// 带同义词容错的匹配逻辑 function matchAnswer(question, options, dictionary) { const correctMeanings = dictionary[question] || []; // 先尝试精确匹配 for (let i = 0; i < options.length; i++) { if (correctMeanings.includes(options[i].text)) { return i; } } // 精确匹配失败,尝试包含匹配 for (let i = 0; i < options.length; i++) { for (const meaning of correctMeanings) { if (options[i].text.includes(meaning) || meaning.includes(options[i].text)) { return i; } } } return -1; // 匹配失败 }

3.3 点击事件的模拟:为什么直接触发click有时不生效

这是很多人卡住的地方。你明明找到了正确的选项元素,也调用了element.click(),但页面就是没反应。原因通常有两个:一是页面的事件监听绑定在父元素上,直接点击子元素不会触发;二是页面使用了框架的合成事件系统,需要触发特定的事件序列才能被识别。

我的解决方案是模拟完整的事件序列,包括mousedown、mouseup和click,并且确保事件对象带有正确的坐标信息。

function simulateClick(element) { const rect = element.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; const eventOptions = { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y }; element.dispatchEvent(new MouseEvent('mousedown', eventOptions)); element.dispatchEvent(new MouseEvent('mouseup', eventOptions)); element.dispatchEvent(new MouseEvent('click', eventOptions)); }

如果这样还是不生效,可以尝试先让元素获得焦点(element.focus()),或者检查页面是否有防抖/节流逻辑导致短时间内多次点击被忽略。

3.4 答题节奏的控制:太快反而容易出问题

脚本跑通之后,很多人会想把速度调到最快。但我实测下来,答题速度太快反而会触发一些问题:页面可能来不及加载下一题,导致脚本读取到旧的题目内容;或者连续快速点击被页面判定为异常行为。

我的建议是在每道题之间加入一个随机延迟,范围控制在800毫秒到1500毫秒之间。这个延迟既不会太慢影响效率,又能给页面足够的加载时间,同时随机性也能让操作节奏更接近真人。

function randomDelay(min = 800, max = 1500) { const delay = Math.floor(Math.random() * (max - min + 1)) + min; return new Promise(resolve => setTimeout(resolve, delay)); }

另外,在点击选项之后,不要立即去读取下一题的内容,而是应该等待页面出现“下一题”按钮或者题目区域的内容发生变化,再做下一步操作。这个等待逻辑可以用MutationObserver来实现,也可以用简单的轮询检测。

4. 脚本注入方式的选择与实操细节

DOM解析脚本写好了,接下来的问题是怎么把它注入到词达人的页面里运行。不同的注入方式适用于不同的使用场景,下面把几种常见方案的操作步骤和注意事项讲清楚。

4.1 浏览器控制台直接粘贴:最快但最临时

这是最简单的验证方式。打开词达人页面,按F12打开开发者工具,切到Console面板,把脚本代码粘贴进去回车执行。优点是零配置、立即可用;缺点是每次刷新页面都要重新粘贴,而且控制台关闭后脚本可能停止运行。

这种方式适合在开发调试阶段快速验证逻辑,不适合日常使用。如果你只是想测试一下脚本能不能跑通,用这种方式最方便。

4.2 浏览器扩展注入:一次配置长期使用

把脚本打包成一个浏览器扩展,可以实现自动注入。基本步骤是创建一个包含manifest.json和脚本文件的文件夹,在浏览器扩展管理页面加载这个文件夹。

{ "manifest_version": 3, "name": "词达人辅助工具", "version": "1.0", "content_scripts": [ { "matches": ["*://*.example.com/*"], "js": ["content.js"], "run_at": "document_idle" } ] }

matches字段需要根据词达人的实际域名来填写,run_at设置为document_idle表示页面加载完成后再注入脚本。这种方式的优点是配置一次之后,每次打开页面脚本都会自动运行,不需要手动操作。

需要注意的是,不同浏览器对扩展的支持程度不同,manifest的版本也有差异。Chrome系浏览器目前主推manifest v3,而一些旧版浏览器可能还在用v2,写法上有区别。

4.3 脚本管理器方案:灵活但需要额外安装

Tampermonkey(油猴)这类脚本管理器是很多人常用的方案。它的优势在于脚本管理方便,可以随时启用/禁用,而且社区里有大量现成的脚本可以参考。操作步骤是:先安装脚本管理器扩展,然后新建一个用户脚本,把代码粘贴进去保存即可。

用户脚本的头部需要包含元数据块,声明脚本的名称、匹配的网址、运行时机等信息:

// ==UserScript== // @name 词达人答题辅助 // @namespace local // @version 1.0 // @description 自动匹配并点击正确选项 // @match *://*.example.com/* // @grant none // ==/UserScript==

这种方案的一个额外好处是,脚本管理器通常提供了调试工具和日志输出功能,排查问题比较方便。

4.4 注入时机的把握:太早太晚都不行

不管用哪种注入方式,时机的把握都很关键。如果脚本在页面还没加载完就执行,会找不到题目元素;如果注入太晚,可能已经错过了第一道题。

我的经验是:在脚本开头加一个等待逻辑,轮询检测题目元素是否出现,出现后再开始答题循环。这样无论注入时机如何,脚本都能正常工作。

async function waitForElement(checkFn, timeout = 10000) { const start = Date.now(); while (Date.now() - start < timeout) { const el = checkFn(); if (el) return el; await new Promise(r => setTimeout(r, 200)); } throw new Error('等待元素超时'); }

5. 实测中反复踩到的坑与排查链路

这部分内容是我在反复调试过程中积累下来的真实经验。每一个坑我都完整记录了从发现问题到定位原因再到修复的整个过程,希望能帮你在遇到类似问题时少走弯路。

5.1 题目读取为空:页面还没渲染完就开始操作

最开始跑脚本的时候,经常出现题目读取为空的情况。日志显示findQuestionElement返回了null,但手动在控制台执行同样的代码却能找到元素。排查了半天才意识到,脚本是在页面DOMContentLoaded事件触发时就执行的,而此时前端框架还没有完成题目数据的渲染。

修复方案很简单:在答题主循环开始之前,先等待题目元素出现。我加了一个waitForElement调用,超时时间设为10秒。如果10秒内题目元素还没出现,就输出一条警告日志并跳过本轮。加上这个等待逻辑之后,题目读取为空的问题基本消失了。

这个坑给我的教训是:永远不要假设页面已经准备好了。前端页面的渲染是异步的,脚本必须做好等待和重试的准备。

5.2 选项点击无效:事件绑定在父元素上

第二个坑是点击选项没反应。我在控制台里手动执行document.querySelector('.option-item').click()是有效的,但脚本里用同样的代码就是不行。后来用开发者工具的Event Listeners面板查看,发现点击事件实际上绑定在选项的父容器上,而不是选项元素本身。

解决方案是把点击事件派发到父容器上,或者使用事件委托的方式,找到实际绑定了监听器的那个元素。我最终采用的是模拟完整鼠标事件序列的方式(前面3.3节有代码),这样无论监听器绑在哪一层都能触发。

5.3 答案匹配错误:同义词和词性变化导致的误判

有一段时间脚本的正确率突然下降,日志显示很多题目都匹配到了错误的选项。抽查了几道题之后发现,问题出在同义词上。比如题目是“abandon”,词库里记录的释义是“放弃”,但选项里出现的是“抛弃”,精确匹配失败后,脚本错误地选择了另一个包含“放”字的选项。

修复方案是改进匹配算法,引入同义词映射表,并且在匹配时优先考虑完整匹配而非部分匹配。我还加了一个置信度评分机制:如果多个选项都部分匹配,选择匹配度最高的那个;如果所有选项的匹配度都低于阈值,则跳过这道题,避免选错。

5.4 脚本运行一段时间后失效:页面更新导致选择器变化

最让人头疼的问题是脚本跑了一段时间后突然失效。排查后发现是词达人更新了前端代码,选项的类名从option-item变成了choice-item,之前写的选择器全部失效。

这个问题的根本解法是减少对类名的依赖,改用文本特征、层级关系等更稳定的定位方式。我在脚本中加入了多重备选选择器:先尝试用类名定位,失败则用文本特征定位,再失败则用父子层级关系定位。这样即使某一层失效,还有其他层可以兜底。

5.5 长时间运行导致内存占用升高

脚本连续运行几个小时后,浏览器标签页的内存占用会明显升高。排查后发现是日志数组不断增长导致的——我最初把每条答题记录都存到一个数组里,用于后续统计,但这个数组没有上限,时间长了就占用了大量内存。

修复方案是给日志数组设置一个最大长度,超过之后自动丢弃最早的记录。同时定期清理不再需要的DOM引用和定时器。这个坑提醒我:长时间运行的脚本一定要注意资源管理,不能只管功能不管开销。

6. 提升脚本稳定性的几个关键设计

踩完上面那些坑之后,我对脚本做了一轮重构,加入了一些提升稳定性的设计。这些设计不一定能让脚本变得“完美”,但确实让它在各种异常情况下的表现好了很多。

6.1 状态机式的答题流程管理

最初的脚本是一个简单的while循环,顺序执行“读题-匹配-点击-等待”四个步骤。这种写法在正常情况下没问题,但一旦某个步骤出错,整个循环就可能卡死或者乱套。

重构后我引入了状态机的思路,把答题流程拆分成几个明确的状态:IDLE(空闲)、READING(读题中)、MATCHING(匹配中)、CLICKING(点击中)、WAITING(等待下一题)。每个状态有明确的进入条件和退出条件,状态之间的转换由事件驱动。这样即使某个状态出错,也能回退到上一个稳定状态重新开始,而不是整个脚本崩溃。

const State = { IDLE: 'idle', READING: 'reading', MATCHING: 'matching', CLICKING: 'clicking', WAITING: 'waiting' }; let currentState = State.IDLE; async function runLoop() { while (true) { try { switch (currentState) { case State.IDLE: currentState = State.READING; break; case State.READING: // 读取题目逻辑 currentState = State.MATCHING; break; // ... 其他状态处理 } } catch (err) { console.error('状态异常,重置到IDLE', err); currentState = State.IDLE; await randomDelay(1000, 2000); } } }

6.2 异常重试与降级机制

任何一步操作都可能失败:题目读取失败、答案匹配失败、点击无效、页面加载超时。对于每一种失败,脚本都应该有对应的处理策略,而不是直接崩溃。

我的做法是为每个关键操作设置重试次数上限(通常是3次),重试间隔逐次递增。如果重试仍然失败,则执行降级操作:比如DOM读取失败就降级到图像识别,答案匹配失败就随机选择一个选项(至少保证流程继续),点击失败就尝试用坐标点击。

这种设计的好处是,即使某个环节出了问题,脚本也不会完全停摆,而是以稍低的质量继续运行。

6.3 答题日志与数据统计

日志不仅仅是用来排查问题的,它还能帮你了解脚本的运行状况。我在脚本中记录了每道题的题目、匹配到的答案、是否正确、耗时等信息。这些数据汇总起来,可以算出脚本的准确率、平均答题速度、失败题目的分布等。

有了这些数据,你就能有针对性地优化。比如发现某类单词的匹配错误率特别高,就可以专门补充这类词的词库;发现某个时间段的答题速度明显变慢,就可以检查是不是页面加载变慢了。

const stats = { total: 0, correct: 0, failed: 0, totalTime: 0 }; function recordAnswer(question, answer, isCorrect, elapsed) { stats.total++; if (isCorrect) stats.correct++; else stats.failed++; stats.totalTime += elapsed; // 保持日志数组不超过500条 if (answerLog.length >= 500) answerLog.shift(); answerLog.push({ question, answer, isCorrect, elapsed, time: Date.now() }); }

7. 关于词库维护和长期使用的几点经验

脚本本身的技术实现只是基础,真正决定使用体验的往往是词库的质量和更新维护。这部分分享一些我在词库管理上的做法,可能对你有帮助。

词库的来源可以有很多种:公开的四六级词汇表、考研词汇表、雅思托福词汇表,甚至可以从词达人本身的题目中反向积累。我的做法是先用公开词库打底,然后在脚本运行过程中,把匹配失败的题目记录下来,定期整理补充到词库中。这样词库会随着使用越来越完善。

词库的存储格式建议用JSON,结构简单、读写方便、兼容性好。每条记录包含单词和释义数组,释义数组里可以放多个同义词,提高匹配成功率。

{ "abandon": ["放弃", "抛弃", "遗弃"], "benefit": ["利益", "好处", "受益"], "crucial": ["关键的", "重要的", "决定性的"] }

词库的更新频率取决于你的使用强度。如果每天刷几百题,建议每周整理一次失败记录;如果只是偶尔用用,一个月整理一次也够了。整理的时候重点关注那些反复出现的失败题目,这些往往是词库覆盖的薄弱环节。

还有一个细节:词达人不同题库的词汇范围可能不同,比如四级题库和六级题库的词汇难度有明显差异。如果你的任务涉及多个题库,建议按题库分别维护词库,或者用一个统一的词库但标注每个词的适用级别。

8. 从自动答题延伸出去的技术思考

折腾词达人脚本这件事,表面上看只是解决了一个具体的重复劳动问题,但过程中涉及的技术点其实有很强的通用性。DOM解析、事件模拟、状态管理、异常处理、日志统计,这些技能放在任何浏览器自动化场景里都是通用的。我后来做其他类似的自动化任务时,很多代码和思路都是直接从词达人脚本里迁移过去的。

另一个感受是,自动化工具的价值不在于“替代人”,而在于“把人从重复劳动中解放出来”。词达人答题本身是有学习价值的,但如果只是为了完成任务量而机械点击,那自动化确实能省下不少时间。关键在于你怎么定义自己的需求——如果目标是记住单词,那脚本只能帮你完成“答题”这个动作,真正的记忆还是得靠自己;如果目标只是完成平台布置的任务量,那脚本就是一个效率工具。

最后说一个实际使用中的小技巧:脚本运行的时候,不要同时开着太多其他标签页。浏览器是单线程处理JavaScript的,标签页太多会导致脚本的执行被延迟,答题速度明显下降。我一般会把其他不相关的标签页关掉,只留词达人页面和脚本运行所需的窗口,这样脚本的响应速度会稳定很多。另外,如果发现脚本突然变慢,可以先检查一下网络状况——词达人的题目加载依赖网络请求,网络不稳定的时候,脚本等待页面加载的时间会变长,整体速度自然就下来了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 20:42:11

LTC6752高速比较器实战:选型、布局与调试全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/27 20:40:04

Cortex-M7与专用DSP内核在实时控制中的架构选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/27 20:39:42

微波考试复习拆解:传输线、波导与S参数考点精讲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/27 20:37:41

Vue3 + ts 实战:选项式 API 与组合式 API 的配置骨架与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华