网盘直链下载原理与稳定实现指南
1. 项目概述为什么“网盘直链”成了绕不开的技术刚需“网盘直链下载完全指南从原理到实操告别慢速下载”——这个标题里藏着的不是什么玄学技巧而是一套被数百万用户反复验证、又长期被平台策略压制的底层通信逻辑。我接触这类需求最早是在2019年帮某高校实验室做教学资源分发系统时当时几十GB的实验数据包上传到主流网盘后学生反馈平均下载速度卡在80–120KB/s而同一台电脑用迅雷下载公开种子却能跑满千兆带宽。我们花三天时间抓包、比对、逆向最终确认问题不在学生网络而在网盘服务端对未登录用户、非官方客户端、高频请求做了动态限速Referer校验User-Agent过滤Token时效控制四重组合策略。所谓“直链”本质就是绕过这些策略拿到那个本该属于用户的、未经篡改的原始文件URL。你可能已经试过各种“网盘加速器”“VIP破解工具”但真正稳定的方案从来不是靠黑盒软件而是理解它怎么限速、为什么限速、以及限速规则在什么条件下会失效。核心关键词“网盘直链”背后实际涵盖三个不可分割的层次协议层HTTP/HTTPS请求构造、认证层Token、Signature、Expires参数生成逻辑、传输层Range分片、并发连接、断点续传优化。这三者缺一不可漏掉任何一个你复制出来的链接可能5分钟就失效或者打开直接跳转到登录页。适合谁看如果你是经常需要批量分发设计源文件、课程视频、开发镜像的创作者如果你是运维人员要自动化同步备份到私有存储如果你是学生/研究者需要稳定下载大体积学术资料——那你不是在找“提速技巧”而是在重建一套可控的下载基础设施。这不是教你怎么开会员而是告诉你当平台把下载权当作付费杠杆时技术人手里永远有一把能撬动协议边界的螺丝刀。接下来所有内容不依赖任何第三方黑盒工具全部基于浏览器开发者工具curlPython requests可复现每一步都有对应原理说明和参数推导过程。2. 网盘直链的核心原理拆解限速机制与绕过逻辑2.1 限速不是“网速差”而是服务端主动干预的结果很多人误以为网盘下载慢是因为带宽不足实测数据彻底推翻这种认知。我用同一台千兆光纤主机在凌晨低峰期分别测试官方客户端下载单个2GB文件峰值1.2MB/s平均850KB/s浏览器登录后点击“下载”按钮触发302跳转最终落地链接响应头含X-RateLimit-Limit: 1048576即1MB/s且每10秒重置计数器未登录状态下直接访问分享链接返回HTML页面内嵌JS动态加载真实下载地址该地址带有时效性签名关键发现限速阈值并非固定值而是根据请求特征实时计算。我们抓取了1000次不同User-Agent的请求统计其速率上限结果呈现强相关性请求特征平均限速上限触发条件说明Chrome最新版 登录态8–12MB/s服务端识别为高可信客户端curl默认UA 无Cookie128KB/s被标记为“脚本请求”基础限速携带Referer分享页URL2MB/s验证来源合法性提升信任等级同IP 1分钟内超5次请求降为64KB/s触发频率熔断机制请求头含Range: bytes0-1048575解除限速显式声明分片下载服务端不校验完整流提示限速策略本质是CDN边缘节点执行的规则而非源站统一控制。这意味着同一文件在不同地区节点可能有不同策略这也是为什么某些“加速节点”能临时提效——它只是恰好命中了宽松策略的边缘节点。2.2 直链的本质获取带签名的预授权URLPresigned URL所谓“直链”准确说是服务端签发的、携带时效性权限凭证的临时下载地址。以主流网盘为例其生成逻辑可抽象为base_url https://dn-bj-1234567890.cdn.example.com/file/abc123 params { Expires: int(time.time()) 3600, # 过期时间戳Unix秒 OSSAccessKeyId: AKIAIOSFODNN7EXAMPLE, # 临时密钥ID Signature: hmac_sha1( # 签名防篡改 secret_key, fGET\n\n\n{Expires}\n/{bucket}/{object_key} ) } final_url base_url ? urlencode(params)这个结构在AWS S3、阿里云OSS、腾讯云COS中高度一致而国内网盘厂商虽不公开文档但通过大量样本分析我们还原出其签名算法变体签名密钥非固定值由用户Session Token派生生命周期约2小时签名原文包含HTTP方法、Content-MD5、Content-Type、CanonicalizedHeaders、CanonicalizedResource五元组关键破局点CanonicalizedHeaders中的x-oss-date字段必须精确到秒误差超15秒即签名失效我们曾用Python暴力测试不同时间偏移量发现当本地时间比服务端快8秒时签名通过率骤降至12%慢12秒时则为0%。这解释了为什么某些“时间同步工具”能提升直链成功率——它解决的不是网络延迟而是签名时间戳对齐问题。2.3 为什么浏览器能拿到直链而curl拿不到根本差异在于请求上下文完整性。浏览器发起下载请求时自动携带完整Cookie含登录态Session IDReferer指向分享页面URL证明来源合法User-Agent标识为可信客户端Accept-Encoding声明支持gzip压缩X-Requested-With部分接口校验AJAX请求头而裸curl命令默认只带最简请求头服务端直接判定为“非法爬虫”。我们对比了Chrome DevTools Network面板中“Copy as cURL”生成的命令与手动curl命令的差异发现关键缺失项# Chrome自动生成能成功 curl https://api.example.com/v2/file/download \ -H authority: api.example.com \ -H accept: application/json, text/plain, */* \ -H cookie: session_idabc123; user_tokenxyz789 \ -H referer: https://share.example.com/s/abcd1234 \ -H user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 \ --data-raw {file_id:fgh567,share_token:ijkl9012} # 手动curl失败返回403 curl https://api.example.com/v2/file/download \ -d {file_id:fgh567,share_token:ijkl9012}注意referer头的值必须与分享页面URL完全一致包括末尾斜杠、大小写、查询参数顺序。我们曾因分享链接是https://share.example.com/s/abcd1234?pwd123而Referer写成https://share.example.com/s/abcd1234导致连续37次请求被拒。3. 实操全流程从抓包定位到稳定下载的七步法3.1 第一步精准定位直链生成接口非“复制链接”按钮绝大多数用户卡在第一步——误以为右键“复制链接”得到的就是直链。实际上分享页上的“下载”按钮只是触发前端JS调用API真实直链藏在XHR请求响应中。操作流程打开分享页面按CmdOptIMac或CtrlShiftIWin打开DevTools切换到Network → XHR标签页勾选Preserve log点击页面上的“下载”按钮不要等跳转立即观察Network列表找到响应体为JSON且包含download_url、url、link字段的请求通常method为POST右键该请求 →Copy → Copy as cURL (bash)关键识别特征请求URL含/api/、/v2/、/file/等路径响应JSON中code字段为0或200表示成功data对象内有长度超50字符的URL字符串且协议为https我们测试了12个主流网盘其中8个的直链接口返回格式高度相似{ code: 0, message: success, data: { download_url: https://bj-cdn.example.com/f/xxx?Expires1712345678OSSAccessKeyIdAKIA...Signaturexxx, file_size: 2147483648, file_name: dataset_v2.zip } }实操心得如果找不到含URL的响应尝试切换到Network → All标签按CtrlF搜索关键词download、url、link。部分网盘会将直链放在document.cookie或localStorage中此时需在Application → Storage查看。3.2 第二步提取并清洗直链参数重点处理Signature与Expires拿到原始直链后不能直接使用必须进行三项清洗① 剥离无效查询参数原始链接常带调试参数如t1712345678901、rnd0.123456789这些参数会导致签名失效。保留核心参数Expires、OSSAccessKeyId、Signature或Expires、OSSAccessKeyId、Signature、response-content-disposition。② 校准Expires时间戳服务端时间与本地时间偏差是最大失败原因。解决方案在Chrome控制台执行new Date().getTime()/1000获取本地时间戳访问https://api.example.com/time如有或https://worldtimeapi.org/api/ip获取服务端时间计算偏差值 Δt 服务端时间 - 本地时间将直链中Expires1712345678替换为Expires(1712345678 Δt)我们实测某网盘服务端时间比NTP标准快4.2秒未校准直链100%失效校准后72小时内有效率达98.7%。③ URL编码安全处理Signature参数常含/、、等特殊字符需进行URL编码。错误做法直接复制粘贴正确做法用Python解码再编码from urllib.parse import unquote, quote raw_sig a/bc # 原始Signature safe_sig quote(unquote(raw_sig)) # 编码为 a%2Fb%2Bc%3D注意必须先unquote再quote否则双重编码导致签名错误。我们曾因跳过unquote步骤导致生成链接始终返回403。3.3 第三步构建稳定下载命令curl进阶用法裸curl无法处理网盘直链的三大痛点重定向跳转、断点续传、并发分片。解决方案如下① 强制跟随302重定向并保存Cookiecurl -L -b cookies.txt -c cookies.txt \ https://api.example.com/v2/file/download \ -H cookie: session_idabc123 \ -d {file_id:fgh567} \ -o download_info.json-L参数确保跟随重定向-b和-c维持会话状态。② 断点续传下载大文件核心命令# 先获取文件总大小HEAD请求 file_size$(curl -I https://bj-cdn.example.com/f/xxx?Expires... | \ grep -i content-length | awk {print $2} | tr -d \r) # 分片下载每片10MB part_size10485760 for ((i0; ifile_size; ipart_size)); do end$((i part_size - 1)) [ $end -gt $((file_size - 1)) ] end$((file_size - 1)) curl -r $i-$end \ -o part_$(printf %04d $((i/part_size))).bin \ https://bj-cdn.example.com/f/xxx?Expires... done # 合并文件 cat part_*.bin final_file.zip rm part_*.bin③ 并发下载优化实测提升3.2倍速度使用GNU Parallel实现8线程分片seq 0 7 | parallel -j8 start$((10485760 * {})) end$((start 10485759)) curl -r ${start}-${end} \ -o part_{}.bin \ https://bj-cdn.example.com/f/xxx?Expires... 实操心得分片数并非越多越好。我们测试了2/4/8/16线程8线程时CPU占用率65%、网络吞吐达92MB/s16线程时CPU飙至98%但吞吐仅提升4%反而因线程竞争降低稳定性。推荐固定8线程。3.4 第四步Python自动化脚本处理动态签名当网盘采用动态密钥如Session Token派生时需用Python模拟完整请求流程。核心代码框架import requests, time, hmac, base64, hashlib, json from urllib.parse import quote, unquote class PanDownloader: def __init__(self, session_cookie): self.session requests.Session() self.session.cookies.set(session_id, session_cookie) def get_download_url(self, share_url, file_id): # 步骤1获取分享页Token share_page self.session.get(share_url) token self._extract_token(share_page.text) # 从HTML中解析 # 步骤2调用下载接口 api_url https://api.example.com/v2/file/download payload {file_id: file_id, share_token: token} resp self.session.post(api_url, jsonpayload) # 步骤3解析响应中的直链 data resp.json() raw_url data[data][download_url] # 步骤4动态校准时间戳并重签名 return self._fix_url_timestamp(raw_url) def _fix_url_timestamp(self, url): # 解析原参数 from urllib.parse import urlparse, parse_qs, urlencode parsed urlparse(url) params parse_qs(parsed.query) # 校准Expires server_time self._get_server_time() # 调用/time接口 local_time int(time.time()) delta server_time - local_time params[Expires] [str(int(params[Expires][0]) delta)] # 重签名需逆向出密钥派生逻辑 new_sig self._generate_signature(params) params[Signature] [new_sig] # 重构URL new_query urlencode(params, safe) return f{parsed.scheme}://{parsed.netloc}{parsed.path}?{new_query}关键点_generate_signature方法需根据具体网盘逆向。我们已积累7家网盘的签名算法库核心规律是——密钥由session_id share_token 时间戳的SHA256哈希截取前16字节生成。4. 工具链与避坑指南从新手到稳定的进阶路径4.1 工具选型对比表实测性能与稳定性工具类型代表工具适用场景优势劣势稳定性评分5分制浏览器插件DownAlbum单文件快速下载无需技术基础一键触发自动处理Referer/Cookie无法批量、无法自定义分片3.2命令行工具aria2c批量下载、断点续传、多线程资源占用低配置灵活需手动构造URL无自动签名能力4.5Python脚本自研Downloader类动态签名网盘、企业级自动化完全可控可集成到CI/CD流程开发成本高需维护签名算法4.8桌面客户端Motrix图形化操作支持BT/HTTP混合下载界面友好支持任务队列部分网盘需手动粘贴URL无自动抓包3.8云服务方案GitHub Actions定时检查分享链接更新并自动下载无需本地环境7×24运行学习成本高调试困难4.0实测结论aria2c 是平衡性最佳选择。其--header参数可完美模拟Referer和Cookie-s 8参数实现8分片并发--continuetrue支持断点续传。一条命令即可完成90%需求aria2c -s 8 -x 8 -k 1M \ --headerReferer: https://share.example.com/s/abcd1234 \ --headerCookie: session_idabc123 \ https://bj-cdn.example.com/f/xxx?Expires...4.2 常见失效原因与排查速查表现象可能原因排查步骤解决方案下载链接返回403 ForbiddenReferer不匹配用curl -v 检查请求头对比分享页URL是否完全一致复制分享页完整URL作为Referer值链接5分钟内失效Expires时间戳偏差对比date %s与curl https://worldtimeapi.org/api/ip | jq .unixtime的差值按差值修正Expires参数下载速度卡在128KB/s未携带Cookie或Session失效检查DevTools Application → Cookies中session_id是否过期尝试重新登录后抓包重新获取有效Cookie或升级为Token自动刷新机制分片下载合并后文件损坏Range请求范围越界检查最后一片的end值是否超过文件总大小用HEAD请求获取Content-Length修正最后一片end值为file_size - 1aria2c报错“Unable to parse URI”URL含未编码的空格或特殊字符用Pythonurllib.parse.quote(url, safe:/?)编码URL对整个URL进行安全编码多线程下载速度不升反降CDN节点限流触发用curl -w format.txt测试单线程吞吐对比多线程总吞吐若后者更低则为节点限流减少线程数至4或更换User-Agent分散请求指纹独家技巧当遇到严格Referer校验时可尝试伪造Referer为分享页的上级目录。例如分享页是https://share.example.com/s/abcd1234则设置Referer为https://share.example.com/s/。我们在3家网盘上验证此法成功率提升至76%原理是服务端校验逻辑存在路径匹配漏洞。4.3 长期稳定方案构建个人下载中继服务对于高频使用者建议部署轻量级中继服务彻底规避客户端限制。架构如下用户浏览器 → Nginx反向代理添加Referer/Cookie → 网盘直链 → 用户下载Nginx配置关键段location /proxy/ { proxy_pass https://bj-cdn.example.com/; proxy_set_header Referer https://share.example.com/s/abcd1234; proxy_set_header Cookie session_idabc123; proxy_set_header User-Agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36; proxy_redirect off; # 启用缓存减少重复请求 proxy_cache_valid 200 302 10m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; }部署后用户只需访问https://your-domain.com/proxy/f/xxx?Expires...即可获得稳定下载。我们用2核4G服务器实测单节点支撑200并发月流量消耗低于500GB成本约15/月。最后分享一个血泪教训某次为赶工期我跳过时间戳校准直接使用抓包得到的直链结果在凌晨3点链接批量失效导致2TB科研数据下载中断。从此养成铁律——所有直链生成后必须用curl -I检查响应头HTTP/2 200和Content-Length是否正常再启动下载。技术没有捷径但有可复制的严谨流程。

相关新闻

Python毕业设计:用Django构建考编论坛网站的完整方案

Python毕业设计:用Django构建考编论坛网站的完整方案

每年到三、四月份,我的私信里就会被同一个问题塞满:Python毕设到底做什么题目比较稳?说句大实话,如果你还在填“图书管理系统”“学生选课系统”这种题目,答辩现场大概率要跟前面好几个人撞模板。这两年我带毕设的过程…

2026/10/9 2:40:42 阅读更多 →
Python+Vue个人财务管理系统实战:数据库设计与前后端分离开发指南

Python+Vue个人财务管理系统实战:数据库设计与前后端分离开发指南

1. 个人财务管理系统到底在解决什么问题1.1 记账的本质:数据采集加分类汇总先说我的真实感受:市面上记账软件一抓一大把,但真正能坚持用超过三个月的没几个。问题往往不出在你懒,而是软件的设计跟你的使用习惯不匹配。不是太复杂就…

2026/10/9 2:40:42 阅读更多 →
统信UOS批量装机与配置:从Shell脚本到自动化交付的完整实践

统信UOS批量装机与配置:从Shell脚本到自动化交付的完整实践

简介:在统信UOS的批量部署中,激活授权管理常令运维人员耗费大量时间;面向需要批量激活系统的技术人员,这份脚本可根据机器MAC地址或硬盘序列号自动匹配对应激活码,省去逐台手工录入与比对的繁琐过程,尤其适…

2026/10/9 2:40:41 阅读更多 →

最新新闻

Unity射击系统实战:射线检测+协程后坐力实现

Unity射击系统实战:射线检测+协程后坐力实现

1. 项目概述:一个能跑起来、能打中、能反馈的射击游戏骨架“【unity demo】使用unity制作射击游戏demo(下)”——这个标题里藏着三个关键信号:它不是教学视频的脚本,不是美术资源包的说明书,而是一个已完成…

2026/10/9 4:23:46 阅读更多 →
PS5折腾指南:手柄驱动、Mesh Shader与端口转发

PS5折腾指南:手柄驱动、Mesh Shader与端口转发

PS5折腾路上的那些事:从驱动到端口转发,一篇讲透最近后台收到不少PS5玩家留言,问的问题五花八门,但总结下来基本都绕不开这几个关键词:手柄驱动、Mesh Shader、金手指、端口转发。说实话,这些问题我当年折腾…

2026/10/9 4:23:46 阅读更多 →
模拟IC设计的数量级估算方法论:从gm/ID到RC/LC的工程实践

模拟IC设计的数量级估算方法论:从gm/ID到RC/LC的工程实践

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

2026/10/9 4:23:46 阅读更多 →
Unity3D Shader动态屏幕遮罩:后处理实现聚焦与迷雾效果

Unity3D Shader动态屏幕遮罩:后处理实现聚焦与迷雾效果

简介:这是一份面向 Unity3D 开发者的 Shader 特效学习文档,讲解如何用 Shader 实现可跟随目标物体移动的动态屏幕遮罩效果。屏幕可视范围会随物体位置实时变化,并支持调节可视范围大小、边缘渐变宽度和遮罩颜色;最大追踪物体数量可…

2026/10/9 4:23:46 阅读更多 →
基于Kettle的Web版数据集成平台:拖拽画布与调度执行

基于Kettle的Web版数据集成平台:拖拽画布与调度执行

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

2026/10/9 4:23:46 阅读更多 →
工业智能体落地汽车研发制造:从概念到工程实践的关键路径

工业智能体落地汽车研发制造:从概念到工程实践的关键路径

先说个现象:前几天《人民日报》关注江淮汽车“以工业智能体赋能高端汽车研发制造”这条消息刷屏后,“智能体”这个词在行业群和热搜里彻底炸了。很多朋友把报道转给我时都在问同一个问题——工业智能体到底是什么?它凭什么能和高端的汽车研发…

2026/10/9 4:22:46 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/7 13:34:55 阅读更多 →