微博评论爬虫实战:登录协议解析与热评增量抓取
简介本资源是一份面向Python初学者与爬虫入门者的实战教程手把手讲解如何抓取微博平台的评论数据解决社交媒体舆情分析、粉丝行为研究等实际场景中的数据采集需求。内容涵盖登录模拟含RSA加密、预登陆参数获取、验证码处理、Cookie持久化管理、HTML/JSON数据解析及CSV存储全流程代码完整可直接运行调试。资源为单文件PDF文档共1页大小379KB内容结构清晰包含库引入说明、全局变量配置、目录创建逻辑、WeiboLogin类实现细节及关键函数注释便于边学边练。已有7702人学习下载适合希望掌握反爬应对策略、理解微博登录机制并构建可复用爬虫框架的学习者。1. 微博评论爬虫不是“点开网页右键另存为”它是一套带登录态、抗反爬、能续爬的完整会话链你有没有试过打开微博某条热门帖想看看底下到底吵成什么样结果翻到第5页就卡住F12 看 Network发现请求全被 302 重定向到 login.sina.com.cn或者更糟——刚输完账号密码弹出验证码图片但 PIL.open() 显示失败终端里只有一行OSError: cannot open resource这不是玄学是微博登录协议在 2023 年后彻底重构的真实切口。这个资源不是教你怎么用 requests.get() 抓静态页面而是交付一套可落地、可调试、可复现的完整登录评论拉取链它包含 RSA2 密码加密逻辑、pcid 验证码动态加载机制、sso 跳转状态机、m.weibo.cn 与 weibo.com 双域 Cookie 同步策略以及最关键的——callback参数如何从 JS 回调中安全提取并用于后续跳转。适合正在做舆情分析、社区情绪建模、或需要真实用户评论语料的 Python 工程师不适合只想复制粘贴就跑通的纯新手——因为这里没有“一键 bypass 验证码”的黑盒只有你能看懂、能改、能 debug 的每一步。它解决的不是“能不能抓”而是“为什么上一秒还行下一秒就 403”、“为什么 max_id 拿不到”、“为什么 CSV 里中文全是乱码”这些血泪问题。2. 登录不是 POST 一次就完事微博 SSO 登录协议拆解与关键参数溯源微博登录早已不是简单的表单提交。它走的是新浪统一认证中心SSO体系整个流程涉及至少 5 次 HTTP 跳转、3 套 Cookie 域名weibo.com / login.sina.com.cn / m.weibo.cn、以及 2 层加密Base64 RSA2。不理解这个链条任何“改个 headers 就能过”的想法都会在第 3 步直接翻车。2.1callback不是固定字符串而是 JS 函数名 时间戳拼接的动态标识在get_server_data()方法中这行代码常被忽略pre_url http://login.sina.com.cn/sso/prelogin.php?entryweibocallbacksinaSSOController.preloginCallBacksu su rsaktmodcheckpin1clientssologin.js(v1.4.19)_ str(int(time.time() * 1000))这里的callbacksinaSSOController.preloginCallBack是关键。它不是随便写的而是前端 JS 中定义的全局回调函数名。服务器返回的数据格式是sinaSSOController.preloginCallBack({retcode:0,servertime:1712345678,nonce:ABCD1234,pubkey:00B123...,rsakv:1234567890})注意eval(...replace(sinaSSOController.preloginCallBack, ))这行代码的本质是把 JS 函数调用包装壳剥掉只留下 JSON 对象。如果某天微博把回调名改成sinaSSOController.preloginV2而你没同步更新callback参数eval就会报SyntaxError。这不是 bug是协议契约。我一般会在pre_data_res.text打印后加一行断言assert sinaSSOController.prelogin in pre_data_res.text, Callback name changed! Check prelogin.php response format2.2rsakv和servertime必须成对使用且有效期极短 5 秒get_password()方法中明文拼接规则是message str(servertime) \t str(nonce) \n str(self.password)注意\t和\n是硬编码分隔符来自微博前端 JS 的encryptPassword函数。servertime是服务器当前时间戳秒级nonce是随机字符串。这两个值一旦过期RSA 加密后的sp字段就会被服务端拒绝。实测发现若prelogin返回后超过 3 秒才发登录请求大概率返回{retcode:404000001,reason:invalid servertime}。因此login()方法里try/except的设计非常务实——它先尝试无验证码登录利用showpin0的情况失败后再触发验证码流程避免无谓耗时。2.3door参数不是“输入验证码”而是 Base64 编码后的图片识别结果get_cha(pcid)下载的cha.jpg是 PNG 格式但微博后端校验的door值是用户肉眼识别后输入的 4 位字母数字组合区分大小写未经任何编码直接作为 POST body 字段发送。原文中self.postdata[door] input(u请输入验证码)是最简实现但生产环境必须替换为 OCR 接口。常见踩坑是有人误以为要传base64.b64encode(open(cha.jpg,rb).read())结果服务端返回{retcode:404000002,reason:invalid door}。正确做法是调用pytesseract.image_to_string()或接入第三方打码平台 API拿到纯文本后直接赋值。2.4 Cookie 同步是双域接力weibo.com登录态 ≠m.weibo.cn可用态WeiboLogin.login()方法末尾有两段关键跳转第一段通过jump_url https://passport.weibo.com/wbsso/login获取uniqueid构造web_weibo_url访问 PC 端主页目的是激活weibo.com域的 Cookie第二段用murl https://login.sina.com.cn/sso/login.php拼接returntypeMETA参数触发replace(...)跳转最终落到m.weibo.cn。这两步缺一不可。漏掉第一段m.weibo.cn请求会返回 302 到登录页漏掉第二段m.weibo.cn的isLogin:true检查永远失败。Mheaders[Host]的反复切换login.sina.com.cn→passport.weibo.cn→m.weibo.cn正是为了匹配不同域名的 Cookie 发送策略。requests.Session()的cookies对象会自动管理多域 Cookie但前提是session.get()的 URL Host 必须与 Cookie Jar 中存储的 domain 匹配。提示调试时可在self.session.cookies.save()后加一行print([c.name for c in self.session.cookies])确认SUB,SUHB,ALF等关键 Cookie 是否已写入Cookie.txt。若为空说明某次跳转未携带 Cookie 或 Host 设置错误。3. 评论拉取不是“翻页循环”max_id机制、分页陷阱与数据去重实战微博热评接口/comments/hotflow的分页逻辑远比page1,2,3复杂。它依赖max_id和max_id_type两个联动参数且max_id本身是服务端生成的 opaque token不能解析、不能预测、不能缓存。很多爬虫在这里卡死不是代码写错而是没吃透这个状态机。3.1max_id是游标cursor不是页码page number原始代码中base_url https://m.weibo.cn/comments/hotflow?id{}mid{}max_id_type0 next_url https://m.weibo.cn/comments/hotflow?id{}mid{}max_id{}max_id_type{}第一次请求用max_id_type0服务端返回 JSON 中的data.max_id是下一个游标值如1234567890123456789同时data.max_id_type会变为1。下一次请求必须用max_id1234567890123456789max_id_type1。若强行用max_id_type0再请求会返回空数据或 400 错误。max_id_type是状态标志0 表示初始请求1 表示后续分页。代码中id_type 1的递增逻辑是正确的但缺少对max_id是否为空的判断——当data.max_id 0或时即表示无更多评论应终止循环。3.2mid和id参数必须严格一致且来源必须是微博详情页 URL代码中start_crawl(cookie_dict, id)的id参数必须与你要爬的微博帖子的mid完全相同。例如某微博 URL 是https://weibo.com/1234567890/AbCdEfGhIjK?refer_flag1001030101_其mid是AbCdEfGhIjK注意不是数字 ID。但原文示例id 4477416430959369是一个数字这其实是旧版微博的id格式。2023 年后主流是字母数字混合的mid。获取方式必须是打开微博 H5 页面m.weibo.cn/status/xxxF12 → Network → Filterhotflow→ 找到第一个请求 → 查看 Query String Parameters → 取mid后的值。若填错返回{ok:0,msg:Parameter error}。3.3 评论嵌套结构需递归解析comments字段是二级评论楼中楼微博热评接口返回的data.data数组中每个元素代表一条一级评论。但部分评论带有comments字段这是该条评论下的回复即“楼中楼”。原文info_parser()函数中if c.get(comments, None): temp [] for cc in c.get(comments): temp.append(info_parser(cc)) wdata.append(info_parser(cc)) # ← 这里有严重 Bug最后一行wdata.append(info_parser(cc))是错的cc是循环变量info_parser(cc)只处理了最后一个cc且temp列表被创建却未使用。正确逻辑应是if comments in c and c[comments]: for cc in c[comments]: nested_row info_parser(cc) nested_row[parent_wid] c[id] # 标记父评论 ID wdata.append(nested_row)否则所有楼中楼数据都会丢失CSV 中只有一级评论。3.4 CSV 中文乱码的根因是utf-8-sig编码与 Excel 兼容性冲突原文open(..., encodingutf-8-sig)是为兼容 Windows Excel 的 BOM 头但csv.writer在utf-8-sig下写入时BOM 会被插入到第一行第一列导致 Excel 打开时首列显示wid。更稳妥的做法是with open({}/{}.csv.format(comment_path, id), modew, encodingutf-8, newline) as f: writer csv.writer(f) writer.writerow([wid, time, text, uid, username, following, followed, gender]) for d in wdata: # 对 text 字段做防错处理避免含换行符破坏 CSV 结构 safe_text d[text].replace(\n, ).replace(\r, ) writer.writerow([ d[wid], d[time], safe_text, d[uid], d[username], d[following], d[followed], d[gender] ])newline是csv模块强制要求否则 Windows 下会多出空行safe_text替换换行符是防止 CSV 解析器将一条评论切分成多行。注意time.sleep(3)是硬编码延时实际部署建议改为random.uniform(2.5, 4.0)避免请求间隔过于规律被风控。4. 避坑5 条血泪经验总结——从登录失败到数据残缺的完整排错路径爬微博评论最让人崩溃的不是代码写不出来而是“明明昨天能跑今天就 403”。以下是我在多个项目中踩过的坑按发生频率排序每条都附带现象、原因和可立即执行的解决方案。4.1 现象prelogin.php返回{retcode:403000001,reason:Invalid app key}原因clientssologin.js(v1.4.19)中的版本号已过期。微博会定期更新登录 JS 版本旧版本 key 被服务器拒绝。解决打开https://login.sina.com.cn/js/目录找最新ssologin.js?vxxx文件提取 URL 中的v参数如v1.4.22替换代码中所有v1.4.19。不要猜必须实测。我一般用curl -I https://login.sina.com.cn/js/ssologin.js看Last-Modified时间戳来判断是否更新。4.2 现象login.php返回{retcode:404000001,reason:invalid servertime}原因prelogin和login两次请求时间差超过 5 秒servertime失效。解决在pre_login()返回sever_data后立即记录时间戳start_time time.time()在构造login_url前检查if time.time() - start_time 4.5: raise Exception(Servertime expired)。若超时重新调用pre_login()。4.3 现象m.weibo.cn请求返回{ok:0,msg:Login required}但pro.text中找不到isLogin:true原因Mheaders[Host]未在每次session.get()前重置。requests.Session()会复用上一次请求的 Host若前一次是passport.weibo.cn这次发给m.weibo.cn却带着Host: passport.weibo.cn服务端直接拒收。解决在每次session.get()前显式设置Mheaders[Host]如原文所示。绝对不要在循环外只设一次。4.4 现象hotflow接口返回{ok:0,msg:Forbidden}且res.status_code 403原因Cookie 过期或不完整。Cookie.txt中缺失SUB或ALF字段或expires时间已过。微博 Cookie 有效期通常为 1~3 天。解决删除Cookie.txt重新运行登录流程或在get_cookies()中增加校验def get_cookies(): cookies cookielib.LWPCookieJar(Cookie.txt) try: cookies.load(ignore_discardTrue, ignore_expiresTrue) except FileNotFoundError: raise Exception(Cookie file not found. Please run login first.) # 检查关键 Cookie 是否存在且未过期 sub_cookie [c for c in cookies if c.name SUB] if not sub_cookie or sub_cookie[0].is_expired(): raise Exception(SUB cookie expired. Re-login required.) return requests.utils.dict_from_cookiejar(cookies)4.5 现象CSV 文件中text字段出现大量None或空字符串原因info_parser()中data[text]可能为None如用户删评但代码未做空值处理。解决在info_parser()中添加防御def info_parser(data): id data.get(id, ) time data.get(created_at, ) text data.get(text, ).strip() or [deleted] # 删除评论标记为 [deleted] user data.get(user, {}) uid user.get(id, ) username user.get(screen_name, ) following user.get(follow_count, 0) followed user.get(followers_count, 0) gender user.get(gender, unknown) return {wid:id,time:time,text:text,uid:uid,username:username,following:following,followed:followed,gender:gender}5. 数据验证与增量爬取用ETag和Last-Modified实现评论变更检测爬虫的价值不在“一次性拉全”而在“持续感知变化”。微博评论是动态流新评论不断涌入旧评论可能被删除或折叠。原代码是全量覆盖模式modew每次运行都重写 CSV无法知道哪些是新增、哪些已消失。我们用 HTTP 协议自带的缓存头低成本实现增量感知。5.1ETag是评论列表的指纹Last-Modified是最后更新时间微博hotflow接口响应头中包含ETag: abc123def456 Last-Modified: Wed, 10 Apr 2024 08:23:45 GMTETag是服务端为当前评论快照生成的唯一哈希只要评论列表不变ETag就不变Last-Modified是服务端认为该列表最后变动的时间。二者结合可精准判断数据是否需更新。5.2 实现增量爬取只在ETag变化时拉取新数据修改start_crawl()函数在首次请求前读取本地缓存的ETagdef start_crawl(cookie_dict, mid): cache_file f{comment_path}/{mid}_cache.json etag_cache {} if os.path.exists(cache_file): with open(cache_file, r, encodingutf-8) as f: etag_cache json.load(f) base_url fhttps://m.weibo.cn/comments/hotflow?id{mid}mid{mid}max_id_type0 headers_with_cache headers.copy() # 发送条件请求 if etag in etag_cache: headers_with_cache[If-None-Match] etag_cache[etag] if last_modified in etag_cache: headers_with_cache[If-Modified-Since] etag_cache[last_modified] res requests.get(urlbase_url, headersheaders_with_cache, cookiescookie_dict) if res.status_code 304: # 未修改直接退出 print(fComments for {mid} unchanged. ETag: {etag_cache.get(etag, N/A)}) return # 200 响应说明有更新继续爬取 if ETag in res.headers: etag_cache[etag] res.headers[ETag] if Last-Modified in res.headers: etag_cache[last_modified] res.headers[Last-Modified] # 保存新 ETag 到缓存 with open(cache_file, w, encodingutf-8) as f: json.dump(etag_cache, f, ensure_asciiFalse, indent2) # 后续分页逻辑保持不变... page 1 comment_count 0 while True: # ... 原有循环体 ... # 在每次成功获取一页后更新缓存文件中的 timestamp etag_cache[last_update] time.strftime(%Y-%m-%d %H:%M:%S, time.localtime()) with open(cache_file, w, encodingutf-8) as f: json.dump(etag_cache, f, ensure_asciiFalse, indent2)5.3 用diff工具对比两次 CSV定位新增/删除评论增量爬取后生成的 CSV 文件名可带上时间戳csv_name f{comment_path}/{mid}_{int(time.time())}.csv然后用 Python 的pandas做差异分析import pandas as pd old_df pd.read_csv(f{comment_path}/{mid}_20240410.csv) new_df pd.read_csv(f{comment_path}/{mid}_20240411.csv) # 找新增评论新有旧无 new_comments new_df[~new_df[wid].isin(old_df[wid])] # 找删除评论旧有新无 deleted_comments old_df[~old_df[wid].isin(new_df[wid])] print(fNew comments: {len(new_comments)}, Deleted: {len(deleted_comments)})这样你的爬虫就从“数据搬运工”升级为“舆情变化探测器”。从那以后我每次部署微博爬虫都强制走一遍ETag缓存校验 csv差异分析流程哪怕只是监控一条重点微博。因为真正的业务价值从来不在“拉了多少条”而在“哪一刻发生了什么变化”。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

自动化测试实战:从Selenium到AI辅助的工程化进阶指南

自动化测试实战:从Selenium到AI辅助的工程化进阶指南

搞了快十年自动化测试,从最初只会用Selenium录制回放,到现在带团队搭框架、写平台,期间踩过的坑比写过的用例还多。经常有人问我自动化测试到底该怎么学、怎么落地,说实话这问题太大,但有一个很直接的感受:…

2026/10/11 19:13:18 阅读更多 →
验证债务:AI编程时代如何让代码质量跟上生成速度

验证债务:AI编程时代如何让代码质量跟上生成速度

1. 验证债务:为什么代码越快,心里越没底最近跟团队复盘一个AI辅助开发的项目,有个数据让我印象很深:功能代码的交付速度比上个季度快了将近一倍,可上线前的Bug率不降反升,有一半的缺陷是在回归测试阶段才暴…

2026/10/11 19:13:18 阅读更多 →
GitHub Copilot Code Review接入CI:从网页评论到质量门禁的工程实践

GitHub Copilot Code Review接入CI:从网页评论到质量门禁的工程实践

我们团队最近做了一次不算大的调整,讨论时间却比预期长不少:把 GitHub Copilot Code Review 从"人在网页上点开看"改成"CI 里自动跑、结果进入合并门禁"。刚开始我以为这只是换一种方式调接口,真正动手才发现&#xff0c…

2026/10/11 19:13:18 阅读更多 →

最新新闻

DeepSeek开源算力地基:FlashMLA与DeepEP如何加速国产大模型?

DeepSeek开源算力地基:FlashMLA与DeepEP如何加速国产大模型?

先说明一下我的第一反应:看到“致敬,DeepSeek 最新开源的不是模型,是国产算力的地基”这个标题,我以为是又一个大模型权重开源了。结果点进仓库一看,里面没有模型文件,躺着的全是 FlashMLA、DeepEP、DeepGE…

2026/10/12 7:08:08 阅读更多 →
NumPy随机函数与广播机制:维度对齐、代码实战与踩坑全解

NumPy随机函数与广播机制:维度对齐、代码实战与踩坑全解

【day 48】随机函数与广播机制,打卡到这个组合的时候,我明显感觉身边不少同学开始卡壳了:随机函数单独用没问题,广播规则单独看也能理解,但真到写代码的时候,要么随机生成的数组形状对不上,要么…

2026/10/12 7:08:08 阅读更多 →
MTCNN人脸检测详解:P-Net、R-Net、O-Net三级网络训练与部署实战

MTCNN人脸检测详解:P-Net、R-Net、O-Net三级网络训练与部署实战

简介:面向深度学习和计算机视觉研究者,这份完整代码基于MTCNN级联卷积网络实现人脸检测,清晰覆盖P-Net候选框提议、R-Net边界框精修、O-Net关键点定位的完整流程。包体共80个文件,以Python源码为核心,包含48个py文件&a…

2026/10/12 7:08:08 阅读更多 →
物联网通信技术选型与架构设计:从链路预算到协议栈的工程实践指南

物联网通信技术选型与架构设计:从链路预算到协议栈的工程实践指南

干了十几年通信,最明显的感觉是:打电话的人越来越少,问"能不能帮我把这个箱子里的定位数据传回来"的人越来越多。物联网这个概念被炒了很多年,别人看到的是智能家居、智慧城市、大风口,我看到的是另一件事—…

2026/10/12 7:08:08 阅读更多 →
MyBatis查询功能全解析:从动态SQL到性能优化的实战指南

MyBatis查询功能全解析:从动态SQL到性能优化的实战指南

项目标题: MyBatis各种查询功能用到一定年头你就会发现,MyBatis的查询功能说难不难,说简单也绝不是写个select标签就完事。日常开发里,动态条件、分页、多表嵌套、批量操作,任何一个场景都能写出好几种不同写法,而每种…

2026/10/12 7:08:08 阅读更多 →
老毛桃UEFI启动盘v7.0:稳过Secure Boot,原生支持NVMe与Win11架构识别

老毛桃UEFI启动盘v7.0:稳过Secure Boot,原生支持NVMe与Win11架构识别

简介:老毛桃U盘启动盘制作工具(UEFI版 装机版)v7.0是一款面向电脑初学者与系统维护人员的轻量级系统辅助工具,专为快速制作兼容UEFI与传统BIOS的U盘启动盘、安装原版Windows系统及执行PE环境下的故障排查而设计。资源包共2个文件&…

2026/10/12 7:07:08 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →