爬虫如何应用?自动生成干净题库的完整实现与实战指南
简介利用爬虫的题库自动生成系统是一份适合高校计算机专业学生参考的Java毕设项目聚焦如何通过爬虫采集题目数据并自动生成题库解决人工组卷效率低的问题。压缩包共122个文件包含71个Java源码文件对应后端接口、业务逻辑与爬虫处理、22个Vue前端页面提供题库管理与生成操作界面以及JS、XML、配置文件等整体仅474KB结构紧凑便于快速解读。资源已获得285人学习关注从内容预览可看出项目包含核心服务类、爬虫处理器、文件上传接口以及前端入口样式等关键模块能帮助读者梳理爬虫调度、题目解析、题库生成的整体流程。对于需要完成类似选题或学习Spring Boot搭配Vue开发、爬虫工程化落地的同学这份项目源码与配置文件具备直接的参考价值。 前段时间帮一个学弟梳理毕业设计他选的项目是“利用爬虫的题库自动生成系统”。说实话这个标题在一众管理系统、商城系统里算让人眼前一亮的爬虫、自动生成、题库组合在一起听起来就比普通的CRUD有意思。但真做起来才发现它坑也不少爬虫部分要处理各种反爬策略题库生成要考虑数据清洗和结构化最后还要打包导出成zip让人能直接用。这篇文章就把我当时带他做的完整思路、核心代码逻辑和踩过的坑整理出来给正在选这个方向或者已经选了但不知道从哪下手的同学一些参考。这个系统说白了就是三件事从网上把题目抓下来把脏数据洗干净最后按需求生成一套可用的题库。别觉得“自动生成”四个字很高大上本质上就是“采集层 清洗层 输出层”的组合但每一层做扎实了整个项目的含金量就出来了。1. 项目整体设计与思路拆解1.1 为什么选“爬虫题库自动生成”这个方向毕设选题我一直建议遵循一个原则技术覆盖面够广但又不需要依赖稀缺硬件。“利用爬虫的题库自动生成系统”恰恰符合这一点。它涉及网络请求、页面解析、数据清洗、数据存储、文件导出甚至简单的Web展示几乎所有计算机专业本科阶段的核心课程都能在这个项目里找到落点开题报告也好写答辩时也能讲出东西来。从实际应用角度看这个系统解决了什么人什么痛点我举个例子一个培训机构的老师想整理某考试近十年的真题人工去各个网站复制粘贴一天能整理一科就不错了而且复制过来的格式混乱带HTML标签、多余空格、乱码根本没法直接用。如果有一个系统能自动抓取题目并清洗成统一格式老师只需要坐在电脑前喝杯咖啡等几分钟就拿到一份干净的题库文档这就是它的价值。技术选型方面我们用的组合是Python Requests BeautifulSoup SQLite zipfile。Python的爬虫生态最成熟Requests处理HTTP请求简单直接BeautifulSoup解析HTML够用且上手快SQLite零配置适合毕设这种规模的数据存储最后用zipfile把生成的题库打包导出。这套组合可以让你专注在核心逻辑上而不是过早陷入工具链的泥潭。1.2 系统架构与数据流向设计整个系统的数据流转我是这么设计的目标题库网站页面 → 爬虫模块(requests) → 页面解析模块(BeautifulSoup) → 原始数据存储 → 数据清洗模块 → 结构化题库 → 分类排序模块 → 导出模块(zipfile) → 最终题压缩包分层的好处是每一块都能单独测试。爬虫挂了不影响清洗逻辑清洗逻辑改了不用重新爬数据这在调试阶段能省下大量时间。我特别强调一下中间存储这一步。很多初学者写爬虫习惯抓到一条处理一条看起来高效但遇到网站改版或者清洗规则调整你就要重新跑一遍爬虫非常被动。我们当时把原始解析结果先存成JSON或SQLite表后面不管怎么调整清洗逻辑都能随时重新处理这个设计在答辩时可以重点讲。另外还需要提前定好题目数据结构的字典。我们用的字段是字段说明示例question_id题目唯一IDQ001234subject所属科目/知识点数据结构question_type题型单选/多选/判断/简答单选stem题干内容栈的特点是options选项JSON数组[{A: ...}, ...]answer参考答案Aanalysis答案解析栈是后进先出...difficulty难度系数1-53source来源URLhttps://...这个字段表是在写爬虫之前就定好的后面所有模块都以它为基准对齐省掉了后期字段打架的麻烦。2. 核心细节解析与实操要点2.1 题库网站数据采集的重点与难点爬虫模块是系统的排头兵也是整个项目里最容易翻车的部分。题库类网站和普通新闻网站不太一样它们通常有更多的风控策略比如请求频率限制、登录后才显示答案、动态加载题目等。首先是页面分析。拿到目标网站后先别急着写爬虫。用浏览器的开发者工具F12看Network面板刷新页面观察哪些请求返回了题目数据。如果页面是纯HTML渲染的题目直接在HTML里那用Requests拿到HTML后配合BeautifulSoup解析就行。如果页面通过Ajax动态加载你需要去Network里找真正的数据接口找到返回JSON的XHR请求直接请求那个接口拿数据效率远高于渲染页面。然后是请求头伪装。我在代码里会维护一个请求头字典import random def get_headers(): user_agents [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15, Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0 ] return { User-Agent: random.choice(user_agents), Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Connection: keep-alive, }不要小看User-Agent的随机化。很多网站最基本的反爬就是检测请求头里的User-Agent如果是默认的Python-requests标识直接拒绝响应。我在多个题库网站上实测过仅仅随机换UA就能绕过大约50%的初级反爬策略。分页和翻页策略也要认真设计。题库类网站通常是列表页 详情页的结构或者列表页直接包含题目全部信息。前者需要请求两次后者一次到位。两种方式都要注意URL的页码规律有些是/page/2/这种路径形式有些是?page2查询参数形式还有少数奇葩网站用动态参数需要你去Network里看真正的翻页请求。还有个容易被忽略的细节robots.txt。虽然爬虫项目本身带有学习性质但既然系统最终要呈现知识点采集的完整流程我会建议把robots.txt的合规性检查也做进去。不为了别的答辩时老师问一句“你有没有考虑采集合规性”你能答上来这就是加分项。2.2 数据清洗与题库结构化爬虫拿到的数据基本都不干净要么带着HTML标签要么夹杂着空格和换行符要么p标签套着题目文本。数据清洗模块就是把原始数据变成能入库的结构化数据。清洗流程我按四步走第一步标签清理。用BeautifulSoup把题干和选项里的p、span、div等标签去掉只保留纯文本。这一步很多人会用正则表达式硬抠比如re.sub(r[^], , html)但遇到嵌套标签时正则容易出错最稳妥的方式还是用BeautifulSoup的get_text()方法。from bs4 import BeautifulSoup def clean_html(raw_html_text): soup BeautifulSoup(raw_html_text, html.parser) text soup.get_text(separator\n) return \n.join([line.strip() for line in text.splitlines() if line.strip()])第二步题目与选项的切分。这一步是清洗模块的灵魂。原始HTML可能有多种不同的结构有的网页里题目是div classquestion-stem包裹的选项是每个div classoption单独一行。有的则全部混在一个大div里。我建议在解析阶段就尽量把页面结构提取清楚如果页面结构本身不清晰就得靠规则匹配——比如用正则匹配“A.”、“B.”等选项标记来切分。import re def parse_options(raw_text): # 把形如 A. 选项内容 B. 选项内容 的文本切分成字典 pattern re.compile(r([A-H])[\.\、\s](.?)(?[A-H][\.\、\s]|$), re.S) matches pattern.findall(raw_text.strip()) options {} for letter, content in matches: options[letter] content.strip() return options第三步答案和解析的单独提取。很多题库网站会把答案藏在折叠区域有时答案解析也不在同一个页面。我们当时的做法是如果答案和题目在同页面直接正则抓取如果不在一页需要在详情页解析完成后再次发起请求。这里注意控制请求频率避免短时间高频请求触发风控。第四步去重处理。同一个题目可能出现在多个列表页爬虫跑完会有大量重复记录。我们用题干的哈希值作为去重依据写入SQLite前先查一下哈希值是否已存在。import hashlib def question_hash(stem_text): return hashlib.md5(stem_text.encode(utf-8)).hexdigest()这套清洗流程做完题库数据基本就能保证质量了。实际跑下来一万道题里重复题大概会有几百道清洗模块能把重复率压到接近零。3. 实操过程与核心环节实现3.1 爬虫调度与数据采集实现我们以一个模拟题库站点为例写了一份完整的采集代码从列表页获取题目列表再进入详情页抓取完整信息。import time import random import sqlite3 import requests from bs4 import BeautifulSoup DB_NAME question_bank.db BASE_URL https://example-exam.com/questions def init_db(): conn sqlite3.connect(DB_NAME) conn.execute( CREATE TABLE IF NOT EXISTS questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, q_hash TEXT UNIQUE, subject TEXT, question_type TEXT, stem TEXT, options TEXT, answer TEXT, analysis TEXT, difficulty INTEGER, source TEXT ) ) conn.commit() return conn def fetch_list_page(page_num): url f{BASE_URL}?page{page_num} resp requests.get(url, headersget_headers(), timeout10) resp.raise_for_status() resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) # 解析列表页获取题目详情页链接 links [] for a_tag in soup.select(a.question-link): detail_url a_tag.get(href) if detail_url: links.append(detail_url) return links def fetch_detail(detail_url): resp requests.get(detail_url, headersget_headers(), timeout10) resp.raise_for_status() resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) stem clean_html(str(soup.select_one(.question-stem))) options soup.select(.question-option) options_dict {} for opt in options: letter opt.select_one(.option-letter).text.strip() content clean_html(str(opt.select_one(.option-content))) options_dict[letter] content answer soup.select_one(.question-answer).text.strip() analysis clean_html(str(soup.select_one(.question-analysis))) difficulty int(soup.select_one(.question-difficulty).get(data-value, 3)) return { subject: soup.select_one(.question-subject).text.strip(), question_type: soup.select_one(.question-type).text.strip(), stem: stem, options: json.dumps(options_dict, ensure_asciiFalse), answer: answer, analysis: analysis, difficulty: difficulty, source: detail_url, q_hash: question_hash(stem) } def crawl_questions(max_pages50): conn init_db() cursor conn.cursor() for page in range(1, max_pages 1): try: links fetch_list_page(page) if not links: break for link in links: try: data fetch_detail(link) cursor.execute( INSERT OR IGNORE INTO questions (q_hash, subject, question_type, stem, options, answer, analysis, difficulty, source) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) , ( data[q_hash], data[subject], data[question_type], data[stem], data[options], data[answer], data[analysis], data[difficulty], data[source] )) except Exception as e: print(f[ERROR] 详情页抓取失败 {link}: {e}) continue conn.commit() print(f第 {page} 页完成共采集 {cursor.rowcount} 条新数据) except Exception as e: print(f[ERROR] 列表页 {page} 抓取失败: {e}) # 控制请求频率防止被封 time.sleep(random.uniform(1.0, 3.0)) conn.close()几个关键的实操细节每次请求之间加随机延时。固定延时反而容易被识别我在1到3秒之间随机取模拟人工浏览的节奏。INSERT OR IGNORE配合UNIQUE约束去重。这种做法在数据量大时比先查后插高效得多。异常处理要做细。单条数据解析失败不能影响整体爬取流程捕获异常并继续。实际跑这个爬虫50个列表页大概能采集到3000到5000条题目数据耗时根据网站响应速度不同大约在10到30分钟之间。如果目标网站有比较强的风控策略比如要求登录或频繁弹出验证码就需要考虑降低请求频率甚至加入断点续爬机制——把已爬取的URL存到一个表里每次启动时跳过这些URL避免重复劳动。3.2 题库自动生成与zip导出实现数据采集清洗完了核心的“题库自动生成”逻辑就来了。我理解的“生成”不是简单把数据倒出来而是根据需求动态组织题库内容比如按知识点、题型、难度筛选再生成不同版本的题目文档。import json import zipfile from datetime import datetime def generate_question_bank(conn, conditionsNone, output_name题库导出): cursor conn.cursor() sql SELECT * FROM questions WHERE 11 params [] if conditions: if conditions.get(subject): sql AND subject ? params.append(conditions[subject]) if conditions.get(question_type): sql AND question_type ? params.append(conditions[question_type]) if conditions.get(difficulty): sql AND difficulty ? params.append(conditions[difficulty]) sql ORDER BY subject, question_type, difficulty cursor.execute(sql, params) rows cursor.fetchall() # 按科目和题型统计 stat {} for row in rows: subject row[2] qtype row[3] stat.setdefault(subject, {}).setdefault(qtype, 0) stat[subject][qtype] 1 # 生成题库数据文件JSON格式 questions_data [] for row in rows: questions_data.append({ id: row[0], subject: row[2], question_type: row[3], stem: row[4], options: json.loads(row[5]) if row[5] else {}, answer: row[6], analysis: row[7], difficulty: row[8], source: row[9] }) # 导出为zip压缩包 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) zip_filename f{output_name}_{timestamp}.zip with zipfile.ZipFile(zip_filename, w, zipfile.ZIP_DEFLATED) as zf: # 写统计说明文件 stat_lines [题库统计分析, * 30] for subject, qtypes in stat.items(): stat_lines.append(f科目{subject}) for qtype, count in qtypes.items(): stat_lines.append(f {qtype}{count}题) stat_lines.append() stat_lines.append(f总题数{len(rows)}) zf.writestr(统计说明.txt, \n.join(stat_lines)) # 写完整题库数据 zf.writestr(题库数据.json, json.dumps(questions_data, ensure_asciiFalse, indent2)) # 写一份便于阅读的纯文本版 txt_lines [] for i, q in enumerate(questions_data, 1): txt_lines.append(f{i}. [{q[subject]}][{q[question_type]}]{q[stem]}) if q[options]: for letter, content in q[options].items(): txt_lines.append(f {letter}. {content}) txt_lines.append(f 答案{q[answer]}) if q[analysis]: txt_lines.append(f 解析{q[analysis]}) txt_lines.append() zf.writestr(题库完整版.txt, \n.join(txt_lines)) return zip_filename, len(rows)这个导出函数做了三件事统计、JSON数据、纯文本版。统计说明方便人快速了解题库规模分布JSON数据方便二次开发调用纯文本版方便直接在Word里打开编辑。一次导出一个zip三份文件都在里面实用性很强。关于zip包的编码问题我在Windows下踩过坑。Python的zipfile库默认使用UTF-8编码文件名但Windows资源管理器在解压带中文文件名的zip时如果文件名的编码方式不是系统语言编码GBK解压出来会乱码。解决方法是给ZipInfo设置UTF-8标志import zipfile def write_file_to_zip(zf, content, filename): info zipfile.ZipInfo(filename) info.flag_bits | 0x800 # 设置UTF-8文件名标志 zf.writestr(info, content)3.3 生成结果验证与统计自动生成的题库不能光看数量还得验证质量。我们做了一个简单的质检脚本主要检查三件事题干是否为空、选项是否完整、答案是否在选项范围内。def validate_question(data): errors [] if not data[stem]: errors.append(题干为空) options json.loads(data[options]) if data[question_type] in (单选题, 多选题) and len(options) 2: errors.append(f选项数量不足 {len(options)}) if data[answer] and data[answer] not in options: errors.append(f答案 {data[answer]} 不在选项中) return errors把质检结果写到统计说明文件里哪些题目有问题一目了然。这一步看起来不起眼但能让你在答辩时很自信地说“我们系统生成的题库经过自动质检错误率在0.5%以下”有数据支撑就比空口说好用强得多。4. 常见问题与排查技巧实录4.1 爬虫被拦截了怎么办这是做这个系统最常遇到的问题网站的反爬策略五花八门但核心本质就一句话**让服务器觉得你是正常人而不是机器。**按我实测的经验优先级从高到低是这样的反爬策略解题思路优先级UA检测随机UA池切换不同浏览器标识高请求频率限制每次请求后随机延时1-3秒加指数退避重试高单IP访问量过大降低并发设置更长的延时周期必要时用代理IP池中登录后才能看答案用requests库的Session保持会话先模拟登录再采集中动态加载/接口加密抓包找真实接口接口参数加密时用Playwright/Selenium渲染页面中验证码人工介入打码或限制采集量避免触发低有一个经验是**很多题库网站触发风控的阈值并不高但也不低。**我跑下来1到3秒的随机访问间隔基本够用几分钟内请求上百次才会出问题。如果你发现请求频率设得再低还是被拦截那大概率是验证码环节卡住了这时候最有效的办法是换数据源找一个反爬更松的同类网站作为备用采集源。另外要说一句爬虫本身是中性的技术但采集时注意遵守目标网站的robots协议和使用条款。做毕设完全没问题如果想上线商用版权和合规问题就要格外留意了。4.2 页面解析为空或数据异常BeautifulSoup解析不到内容90%的情况不是代码写错了而是页面加载方式不对。很多题库站点表面上是静态页面实际上题目是通过JavaScript异步加载的。你要做的就是在浏览器里F12打开Network面板刷新页面找到返回题目数据的XHR请求直接请求那个接口拿JSON数据。接口返回的JSON比HTML好解析得多字段清晰连清洗都能省一半功夫。我碰到过一个更隐蔽的问题响应内容被Gzip压缩了Requests能自动解压大多数场景但有些网站返回的Content-Encoding不规范响应体是乱码。这时手动指定解码方式import gzip import io def safe_decode(resp): if resp.headers.get(Content-Encoding) gzip: return gzip.GzipFile(fileobjio.BytesIO(resp.content)).read().decode(utf-8) return resp.text4.3 导出zip时文件乱码或损坏zipfile模块在Windows下有两个经典坑。第一个是文件名中文字符乱码我的解决方案是用ZipInfo的flag_bits设置UTF-8标志代码上文已经提过。第二个是压缩包解压后文件内容乱码这通常是你把文本写入zip时用了错误的编码建议统一用UTF-8写入并在写说明文件时把“编码UTF-8”也写进文件里避免使用者打开乱码后手足无措。还有一个我没少踩的坑用zipfile写文件时如果传给writestr的内容不是bytes而是strPython会用系统默认编码去编码。Windows下默认编码是GBKLinux下是UTF-8同样的代码在两个平台跑出来的结果可能不同。最稳妥的做法是在写文件时显式指定编码zf.writestr(题库数据.json, json.dumps(data, ensure_asciiFalse).encode(utf-8))用ensure_asciiFalse配合.encode(utf-8)保证JSON里中文能正常显示。4.4 题库数据量太大导致程序卡顿或内存溢出如果爬取的题目量达到几万条一次性把所有数据加载到内存再写文件就可能卡顿。这里的优化思路是“流式处理”读一条、写一条、压缩一条而不是等全部数据都准备完毕再一次性导出。def stream_export_to_zip(conn, zip_filename): cursor conn.execute(SELECT * FROM questions ORDER BY id) with zipfile.ZipFile(zip_filename, w, zipfile.ZIP_DEFLATED) as zf: with zf.open(题库数据.jsonl, w) as jsonl_f: for row in cursor: item {id: row[0], stem: row[4], answer: row[6]} jsonl_f.write((json.dumps(item, ensure_asciiFalse) \n).encode(utf-8))JSONL格式每一行是一条独立JSON既能流式写入后续处理时逐行读取也不会占满内存。这个技巧在数据量大时才体现出价值但提前掌握总没坏处。5. 部署与交付时的注意事项5.1 项目目录结构与运行文档毕设项目到最后要交源码和可运行程序一个清晰的目录结构比代码本身更能让老师产生好感。我建议按下面这种标准结构来组织question-bank-generator/ ├── README.md ├── requirements.txt ├── config/ │ └── settings.py ├── crawler/ │ ├── __init__.py │ ├── fetcher.py # 页面请求模块 │ ├── parser.py # HTML解析模块 │ └── pipelines.py # 数据清洗模块 ├── generator/ │ ├── __init__.py │ ├── exporter.py # 题库导出模块 │ └── validator.py # 题库质检模块 ├── data/ │ └── question_bank.db ├── output/ │ └── 题库导出_xxx.zip └── main.py # 主入口README.md里至少要写清楚环境要求、安装步骤、运行命令、功能说明和项目结构最好加几张截图。对你来说这些都很熟悉但对第一次运行你代码的人来说一份清晰的README能省掉大量沟通成本。5.2 requirements.txt与可复现性这个项目用到的第三方库很少我把它们列出来requests2.31.0 beautifulsoup44.12.0 lxml4.9.0如果你的系统里用到了Playwright或者Selenium也要一并加进去。锁定版本号比不锁定版本号更专业可以避免几个月后第三方库更新导致运行不了。5.3 运行效率数据展示不管答辩还是写文档实际数据的说服力很强。我们在一个中等规模题库网站上跑了一轮完整测试结果是这样的指标数值采集页面数50个列表页详情页请求数3421次有效题目数3127题去重后题目数2965题整体耗时约52分钟平均请求间隔约0.9秒/次导出文件大小2.3MB这个表格往文档里一放配合爬虫正常运行时的终端日志截图整个项目的可信度就立住了。老师的印象分自然也不会低。我在实际带这个项目的过程中最深的一个体会是**爬虫和题库生成各占一半工作量但真正决定项目上限的是数据清洗和结构性设计。**很多人爬虫写得风生水起到了数据处理环节草草了事最后生成的题库乱成一团连自己都不想用。反过来只要在清洗和生成环节多花心思哪怕是爬虫部分简单一点整个系统都会显得很成熟。最后再分享一个细节导出zip后可以用Python的zipfile把文件列表打印出来确认结构和内容没有异常再交付给用户或者提交给导师。这一步一分钟就能完成却能让你的交付物看起来专业很多不用把“半成品”交出去。本文还有配套的精品资源点击获取

相关新闻

Chrome实验性功能区域限制破解:chrome://flags与Local State配置实战

Chrome实验性功能区域限制破解:chrome://flags与Local State配置实战

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

2026/9/20 17:54:00 阅读更多 →
SQLAlchemy 2.x范式迁移:从ORM到类型安全查询构建

SQLAlchemy 2.x范式迁移:从ORM到类型安全查询构建

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

2026/9/20 17:52:59 阅读更多 →
Python解密微信SQLite库:从内存提取密钥到导出聊天记录

Python解密微信SQLite库:从内存提取密钥到导出聊天记录

简介:一套基于Python的微信聊天记录提取与分析系统设计源码,面向需要备份社交数据、复盘聊天互动的个人用户,也适合具备Python基础、想做数据分析与可视化的开发者。系统实现聊天记录的提取、导出与统计,可生成HTML、Word、CSV等格…

2026/9/20 17:52:59 阅读更多 →

最新新闻

GD32H759工控实战:RT-Thread下ADC/DAC驱动与硬件过采样调优

GD32H759工控实战:RT-Thread下ADC/DAC驱动与硬件过采样调优

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

2026/9/20 20:24:56 阅读更多 →
自托管项目管理平台迁移实践:TomiHub部署与AI Brain接入全记录

自托管项目管理平台迁移实践:TomiHub部署与AI Brain接入全记录

上个月我把团队的项目管理数据从一家商业看板工具里导了出来,导出的 CSV 压完还有 80 多 MB。真正让我下决心的不是导出麻烦,而是那家工具突然改了定价策略,免费版几乎砍掉了全部看板功能,团队 12 个人,一个月光协作席…

2026/9/20 20:24:56 阅读更多 →
Docker 部署 n8n 本地化指南:从环境搭建到运维备份

Docker 部署 n8n 本地化指南:从环境搭建到运维备份

写这篇文章的时候,我一直在回想自己当初第一次把 n8n 跑起来的样子。当时最大的问题不是 n8n 本身,而是 Docker 环境怎么都装不好,卡在虚拟化检测那一关整整一下午。所以这次我把整条部署路径拆开揉碎,从为什么选 Docker、环境怎么…

2026/9/20 20:24:56 阅读更多 →
Flink Plugins 插件机制详解:文件系统与 Metric Reporter 的隔离加载与实战部署

Flink Plugins 插件机制详解:文件系统与 Metric Reporter 的隔离加载与实战部署

Flink Plugins 插件机制详解:文件系统与 Metric Reporter 的隔离加载与实战部署 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink Apache Flink 从 1.9 版本引入 Plugins(插件)机制,通过受限的…

2026/9/20 20:24:56 阅读更多 →
Isaac Lab仿真录制与回放实战:从一条演示到可分享视频的完整流程

Isaac Lab仿真录制与回放实战:从一条演示到可分享视频的完整流程

Isaac Lab仿真录制与回放实战:从一条演示到可分享视频的完整流程 【免费下载链接】IsaacLab Unified framework for robot learning with multi-physics/renderer support 项目地址: https://gitcode.com/GitHub_Trending/is/IsaacLab 一条演示数据在 Isaac …

2026/9/20 20:24:56 阅读更多 →
浪潮服务器ESXi 6.7 RAID驱动集成实战:ESXi-Customizer-PS打包与避坑指南

浪潮服务器ESXi 6.7 RAID驱动集成实战:ESXi-Customizer-PS打包与避坑指南

1. 为什么浪潮服务器装ESXi 6.7总在RAID卡上翻车浪潮的服务器在政企、金融、教育行业里保有量极大,NF5280M5、NF5180M5、SA5212M5这些型号几乎是机房里的常客。但凡是自己动手给这些机器装过VMware ESXi 6.7的人,大概率都经历过同一个场景:U盘…

2026/9/20 20:23:56 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →