尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
全国天气数据采集:从爬虫脚本到可复用数据管道的工程化实践
简介这是一套覆盖全国34个省级行政区、2290个地区的天气数据采集工程面向爬虫入门、数据处理与数据可视化学习者解决2011—2024年长周期历史天气数据的获取与分析难题。包内共300个文件以261个CSV数据表为核心存储各地区逐日气温、风向、风力、生活指数、健康指数、旅游指数及天气预警等字段29个Python脚本分别处理抓取、解析、清洗和合并任务另有6个XML配置文件与2个Jupyter Notebook用于梳理采集逻辑并辅助探索性分析整体压缩包仅1.23MB便于快速下载和归档。目前已有163人学习下载。通过这套资料读者可以拿到一份可直接导入数据分析工具的全国天气数据集框架并跟随源码理解从数据源选择、API优先策略、网页爬虫设计到结果表落地的完整路径同时可举一反三将其中断点续传、异常重试、字段规整等处理技巧迁移到其他行业数据采集项目中是积累实战经验的实用起点。1. 全国天气数据采集从“爬虫脚本”到“可复用数据管道”一个反直觉的结论全国天气数据采集最难的从来不是爬虫本身而是“造数据”这件事。我第一次拆这套源码时以为核心价值在 requests 和 BeautifulSoup看完整包才发现真正值得反复读的是调度、去重和落库那部分——三者加起来占了项目一半以上的代码量也正是这部分让脚本从“能跑一次”变成“能当数据源用”。这套源码适合三类人想拿真实天气数据集做分析或训练模型的同学刚摸爬虫想进阶到工程化采集的开发者还有需要在离线环境里自建天气数据台账的团队。它不依赖任何付费气象接口靠公开网页和自身维护的城市编码表能采回全国省市县三级的天气快照并且把每次采集结果整理成可以直接查询和导出的 SQLite 数据文件。2. 技术选型与项目结构一个朴素但耐用的预处理设计2.1 技术栈选型与第三方库的取舍这套源码没有引入重型框架核心链路是 requests lxml Redis SQLite 的朴素组合。requests 负责发请求lxml 负责解析 HTMLRedis 用来做 URL 去重和增量判断SQLite 作为最终数据落库。对一个以“最终产出数据集”为目标的采集项目来说这套组合的性价比非常高requests 足够轻lxml 在性能和安全上都比正则解析强Redis 只有几百行调用SQLite 则让数据文件可以直接拷走不用额外部署数据库服务。我见过不少人拿到这种项目第一反应是“为什么不用 Scrapy”。拆完代码我反而理解了这个决定Scrapy 的抓取循环、中间件、管道都是框架自动帮你跑的调试时需要理解框架的事件模型这套源码要的是“每一步都可以被单测”的控制感。比如某个省份解析失败你可以直接在 parser 里打断点看传入的 HTML 长什么样而不是去翻 Scrapy 的下载器中间件日志。简单说框架适合规模化放大而这里要的是把采集逻辑本身做透。第三方库的选择还有一个隐藏点lxml 的 XPath 支持远比 BeautifulSoup 的 find 系列更紧凑尤其当页面里的字段位置经常变动时改一个 XPath 表达式比改动一串嵌套 find 调用要快得多。项目里大量使用contains(class, xxx)这类容错写法也说明作者在设计之初就预料到了页面改版。requests.Session 被显式传入 fetcher这个做法很多人忽略——Session 会复用底层的 TCP 连接对全国几千个城市的连续请求来说连接复用的收益非常可观。2.2 目录结构与模块边界整个项目是一个扁平但边界清晰的分层结构源码包里按采集、解析、清洗、存储、调度划分了五个核心动作weather_crawler/ ├── config/ │ ├── city_code.json # 全国城市编码表 │ └── settings.py # 请求间隔、超时、重试次数、输出路径 ├── core/ │ ├── fetcher.py # 发送请求、处理响应、编码修正 │ ├── parser.py # 解析HTML表格、抽取字段 │ ├── cleaner.py # 清洗异常值、统一单位、去除占位符 │ └── storage.py # 写SQLite、处理覆盖与追加 ├── scheduler/ │ ├── runner.py # 编排主流程取城市、抓取、解析、入库 │ └── dedup.py # Redis去重、URL指纹 ├── tools/ │ └── update_city_code.py # 城市编码表更新工具 └── output/ └── weather_records.db # 采集结果数据文件这个目录设计的核心原则是“采集、解析、存储”三层分离。fetcher 只负责拿到响应文本不知道页面里有什么字段parser 只负责从 HTML 中抽取字段不关心数据从哪来storage 只负责写库不关心字段名是否清洗干净。边界清晰带来的直接收益是某天气站页面改版导致解析失败时你只需要改 parser 里的 XPath不需要动网络层当你想把输出改成 CSV 或 Parquet 时也完全不碰采集逻辑。scheduler 和 tools 是两个容易被忽略但很有价值的目录。scheduler 把整个链路串成一条可重复执行的命令tools 里的update_city_code.py则是专门应对行政区划变更的更新脚本。模块边界的收益往往在维护期才体现出来这套项目的经验是——边界越清晰二次开发成本越低。2.3 配置项的默认值与改写方法config/settings.py是全项目的“总控制台”值得每一项都看明白。请求间隔默认设为 1.2 秒配合重试 2 次的设计可以让单机采集保持在一个相对安全的频率。超时默认是 10 秒这是我在多个场景下反复试出来的折中值低于 5 秒在高延迟网络下误杀太多高于 20 秒会拖慢整体调度。代码里需要调整的地方只有两处——如果目标源有限流就把间隔调大如果只想采集省级数据就把城市编码表截断。# config/settings.py REQUEST_INTERVAL 1.2 # 请求间隔单位秒调大更安全调小更快 TIMEOUT 10 # 单次请求超时重试前等待时长 RETRY_TIMES 2 # 失败重试次数403时建议设为0 ENABLE_REDIS_DEDUP True # 是否启用Redis去重无Redis时改为False DB_PATH output/weather_records.db # 数据文件输出位置这里我习惯把所有可调项集中成配置常量而不是散落在各模块里因为当你需要给采集任务提速或限速时只需要改一个文件不用从头翻找魔数。字段说明很简单REQUEST_INTERVAL控制抓取频率调小会让任务变快但更容易触发风控ENABLE_REDIS_DEDUP是在无 Redis 环境下跑通的开关DB_PATH决定最终数据文件的存放位置建议改成绝对路径避免从不同目录运行时产生多个副本。2.4 存储选型SQLite 为什么够用把数据落进 SQLite 而不是 MySQL 或 CSV是这套代码一个很清醒的决策。采集项目的数据量级一般是“城市数 × 天数”即使连续跑一年全国县级数据也就几十万行SQLite 单文件完全可以扛住。更重要的是它让这套源码拿到手就能直接用不需要安装数据库服务不需要配置账号密码跑完脚本当场就能用 sqlite3 查询结果。如果换成 MySQL第一件事就是建库建账号这对只想拿数据做分析的读者来说是一个极大的劝退点。CSV 虽然更轻但没有类型约束和索引做增量更新时又会遇到“重复写入 vs 手工标记”的两难。SQLite 刚好卡在中间有 SQL 能力又有单文件便携性几乎是为这类数据集项目量身定做的。项目还把建表语句直接放在 storage.py 的初始化函数里正好呼应了“拿到手就跑”的设计目标。3. 核心模块拆解一个请求从进入到入库的完整链路3.1 数据源分析公开页面里也有结构化信息正式写爬虫之前第一件事是“看源码结构”。这套采集器锁定的数据源是公开天气页面页面里通常是一张字段固定的表格城市、日期、最高气温、最低气温、天气现象、风力风向。不同站点的页面结构差异很大有些直接把数据写在 table 的 class 里有些则需要从多个 div 里拼接字段。项目作者的应对方式是先把 HTML 保存下来做静态分析确认每一项数据对应的 XPath再开始写解析器。我在拆这个项目时复现了同样的做法用浏览器开发者工具选中表格节点复制 XPath再对照源码里的 parser 做字段坐标映射。这套流程虽然没有写成文档但 parser 里的注释已经足够当说明书看每个字段旁边都标了“对应页面第几列”这在后期维护时能省下大量排查时间。3.2 fetcher请求头伪装与状态码处理fetcher.py 是整个采集链路的第一环也是反爬博弈的主战场。源码里请求头伪装做得很完整User-Agent 使用接近真实浏览器的完整字符串Accept-Language 固定为中文避免拿到默认语言页而不是实际数据页。函数接收外部传入的 session 对象而不是自己创建连接这是为了让多个页面共享 TCP 连接池。# core/fetcher.py import requests from config.settings import TIMEOUT, RETRY_TIMES HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36, Accept-Language: zh-CN,zh;q0.9, } def fetch(url: str, session: requests.Session) - str: for attempt in range(1, RETRY_TIMES 1): try: resp session.get(url, headersHEADERS, timeoutTIMEOUT) if resp.status_code 200: resp.encoding utf-8 # 显式指定编码避免自动识别翻车 return resp.text elif resp.status_code in (401, 403): print(f[warn] 第{attempt}次请求被拒绝: {url}) else: print(f[warn] 非预期状态码 {resp.status_code}: {url}) except requests.RequestException as e: print(f[error] 请求异常: {e}, 重试 {attempt}/{RETRY_TIMES}) return 逻辑说明代码先构造了一套贴近真实浏览器的 HTTP 头其中 User-Agent 是必须的很多站点会直接拒绝无 UA 的请求。循环里的三分支覆盖了三种典型情况200 直接返回文本403 说明 IP 或 UA 被识别打印警告后继续重试网络异常则捕获后进入下一次循环。最后返回空字符串表示失败调度器会据此跳过本轮采集。参数方面RETRY_TIMES2是一个平衡值重试太多会在风控触发时浪费大量时间。resp.encoding utf-8这一行特别值得注意requests 库有时会把中文页面自动识别成其他编码导致后续解析全部乱码显式指定编码是从根本上绕过这个不确定性的做法。3.3 parserXPath 解析与字段坐标定义parser 的核心任务是从 HTML 表格中抽取所需列。源码里使用的是 lxml 的 etree 模块先把 HTML 转成 Element 对象再通过 XPath 定位到字段所在节点。项目里大量使用contains(class, weather-table)而不是精确匹配 class 名这是因为某些站点会在 class 名后面附加随机编号精确匹配会漏数据。# core/parser.py from lxml import etree def parse_weather(html: str) - dict: root etree.HTML(html) rows root.xpath(//table[contains(class, weather-table)]//tr) data {} for row in rows[1:]: # 跳过头部的字段名称行 cells row.xpath(.//td/text()) if len(cells) 5: city cells[0].strip() data[city] { high_temp: cells[1].strip(), low_temp: cells[2].strip(), weather: cells[3].strip(), wind: cells[4].strip(), } return data逻辑说明rows[1:]跳过了表头避免把字段名当数据解析。len(cells) 5是一个防御性判断避免某些空行或广告行混入结果。最后的字典嵌套结构方便后续按城市名索引同时也天然适合转成 JSON 或写 SQLite。这里的字段坐标依赖页面结构稳定一旦发布方调整了表格列顺序就需要重新定位 XPath。参数里最值得关注的是strip()方法的使用。网页文本经常携带全角空格、不换行空格等隐形字符不清理会导致入库后有脏数据。项目把这层清理单独放到了 cleaner 里而不是 parser 中好处是 parser 里的逻辑可以保持纯粹只在最终输出前做一次统一清洗。3.4 cleaner异常值修补与单位统一采集到的文本不能直接入库cleaner 负责处理两类典型问题。第一类是各种“无数据”占位符比如“--”“—”“null”“暂无”第二类是单位混用温度列里可能带“℃”后缀风力列可能带“级”字。如果把这些原样写进 SQLite后续做数值比较时就会因为类型是字符串而出问题。# core/cleaner.py import re def clean_field(value: str) - str: value value.replace(\u3000, ).replace(\xa0, ).strip() if value in (--, —, null, 暂无): return m re.search(r(-?\d), value) return m.group(1) if m else 逻辑说明第一步去除全角空格和不换行空格这两个字符是网页数据里最常见的隐形污染源。第二步把各种“无数据”占位符统一成空字符串避免数据库里存一堆不同写法。最后一步用正则抽取第一个带符号整数把“最高气温23℃”这类含后缀的字符串清洗成“23”方便后续直接参与数值计算。这段代码看似简单但对分析的帮助是实打实的。比如你要统计全国最高气温分布如果字段里混着“23℃”“23”“23.0”排序和聚合结果都会失真。清洗层的核心价值就是把“给人看”的网页文本变成“给程序分析”的干净字段。4. 从采集到落地调度、去重与增量更新的工程化细节4.1 调度策略单机串行的稳定性优先调度器采用的是单机串行模式整体思路是“宁可慢一点不能错一门”。runner.py 维护一个城市列表逐个执行“抓取 → 解析 → 清洗 → 存储”每次循环结束后 sleep 固定间隔。这个设计天然避免了多线程并发的频率惩罚也让任务随时可以中断而不产生脏数据。# scheduler/runner.py import time from config.settings import REQUEST_INTERVAL from core.fetcher import fetch from core.parser import parse_weather from core.cleaner import clean_field from core.storage import save_record def run(city_list: list[str], mode: str daily): session create_session() for city in city_list: url build_url(city) html fetch(url, session) if not html: continue parsed parse_weather(html) for name, fields in parsed.items(): cleaned {k: clean_field(v) for k, v in fields.items()} save_record(name, cleaned, mode) time.sleep(REQUEST_INTERVAL) # 限速核心不能省略逻辑说明fetch返回空字符串时直接continue空 HTML 不会进入解析逻辑避免后面抛出一堆异常。mode参数决定写入方式daily模式只覆盖当天记录第二天重跑时更新同一批数据full模式则追加历史适合积累长期天气数据集。create_session()封装了 Session 创建过程让整个调度周期内复用同一个连接池。调度参数里city_list的顺序会影响整体耗时因为编码表按行政区域排列相邻城市通常在同一网络区域连接复用的效果更明显。如果城市列表特别大建议先切片分批跑避免长时间占用内存持有 session。REQUEST_INTERVAL是这段代码里最值得调优的参数设成 0.5 秒可能在半小时内被限流设成 3 秒则牺牲速度换稳定具体要看目标站的容忍度。4.2 去重设计让“重复采集”变成“跳过采集”全国天气数据采集的一大痛点是周期重复同一天的数据可能因脚本重跑、断点续采而重复入库。项目用 Redis 的 SET 记录已采集过的 URL 指纹每次fetch前先判断指纹是否存在存在就直接跳过。这个设计把重复请求挡在了网络层之前减少的不只是存储占用还有目标站的请求压力。# scheduler/dedup.py import hashlib import redis r redis.Redis(hostlocalhost, port6379, db0) def url_fingerprint(url: str) - str: return hashlib.md5(url.encode(utf-8)).hexdigest() def is_fetched(url: str) - bool: fp url_fingerprint(url) if r.sismember(weather:fetched_urls, fp): return True r.sadd(weather:fetched_urls, fp) return False逻辑说明MD5 把完整 URL 压缩成固定长度的十六进制串与直接存储 URL 相比在千万级请求下能显著节省 Redis 内存。sismember判断指纹是否已存在存在则返回 True 表示跳过不存在则写入并返回 False调度器据此继续采集。这里有一个工程经验值得记录指纹集合的 key 命名是“项目前缀:用途:模块”结构weather:fetched_urls中weather是项目前缀fetched_urls标识用途。这样当数据量超过 Redis 内存上限时可以单独清理这个 key 而不影响其他业务数据。如果你不想依赖 Redis也可以把判断逻辑换成查询 SQLite 上的唯一索引效果等价但速度会慢一些。4.3 存储落库表结构设计与导出路径storage.py 的表设计遵循一个“能直接分析”的原则城市、日期、温度、天气现象、风力都单独成列日期用YYYY-MM-DD格式而非时间戳字符串方便 SQL 直接按天聚合。INSERT OR REPLACE是存储层的核心语句它依赖表上的唯一索引判断记录是否存在存在则整体替换不存在则正常插入。# core/storage.py import sqlite3 from config.settings import DB_PATH def init_db(): conn sqlite3.connect(DB_PATH) conn.execute( CREATE TABLE IF NOT EXISTS weather_daily ( city TEXT NOT NULL, date TEXT NOT NULL, high_temp TEXT, low_temp TEXT, weather TEXT, wind TEXT, UNIQUE(city, date) ) ) conn.commit() conn.close() def save_record(city: str, fields: dict, mode: str): conn sqlite3.connect(DB_PATH) conn.execute( INSERT OR REPLACE INTO weather_daily (city, date, high_temp, low_temp, weather, wind) VALUES (?, ?, ?, ?, ?, ?) , (city, fields[date], fields[high_temp], fields[low_temp], fields[weather], fields[wind])) conn.commit() conn.close()逻辑说明UNIQUE(city, date)建的是联合唯一索引用来保证同一城市同一天只有一条记录。INSERT OR REPLACE利用这个索引做覆盖写让daily模式天然变成“更新当天数据”不需要额外写删除逻辑。字段顺序必须与建表语句严格对齐否则 SQLite 会按位置错误写入。导出方面SQLite 本身就提供了最方便的路径。跑完采集后直接执行一行 SQL 就能拿到 CSVsqlite3 -header -csv output/weather_records.db \ SELECT * FROM weather_daily WHERE date 2025-06-01; weather_20250601.csv这条命令从数据文件里筛选某一天的全量记录并导出为带表头的 CSV已经是 pandas 可以直接读取的格式。如果你需要长期保留历史数据用于趋势分析建议每月做一次导出归档再清理主库。4.4 失败恢复断点续采与日志回看全国几千个城市的采集任务不可能一次跑完失败恢复能力决定这个项目能不能真正落地。runner.py 里没有用复杂的任务队列而是依靠日志输出和 Redis 去重共同实现断点续采。具体逻辑是每个城市处理完后去重集合里就已经存在对应的 URL 指纹下次重跑时这些城市会被自动跳过只有失败的部分会重新请求。我把这个机制称为“日志即断点”。运行任务时把print输出重定向到日志文件重跑时先grep看最后处理的城市是哪一个就能判断从哪里断的。如果你想把断点续采做得更精准可以给每个城市单独记录状态pending/success/failed失败的城市进入重试队列。但就这套源码的定位而言Redis 去重已经覆盖了 90% 的重复场景多一个状态表反而是维护负担。5. 天气爬虫常见问题排查从 403 到字段乱码的踩坑记录5.1 画面抓取到一半开始大量返回 403跑全国县级天气时最常遇到的情况是前两百个城市正常第两百个开始连续 403最后程序卡在重试循环里死磕。现象是请求频率超过了目标源的单 IP 滑动窗口限制前面短间隔的请求触发了风控。解决分两层。应急层把REQUEST_INTERVAL从 1.2 秒调到 3 秒以上同时把重试策略改成遇到 403 直接跳过而不是重试因为重试只会让风控越来越严重。长效层在 fetcher 里接入代理池接口按权重轮换出口 IP或者干脆切换一个备选数据源。对单机应用我更倾向于前者——调低采集频率换取稳定毕竟这个项目的重点是把数据采集做成数据集而不是挑战目标源的安全策略。5.2 画面入库后的城市名与编码表对不上采集结果里出现城市名对不上编码表比如库里存的是“某州”业务方习惯叫“某市”实际是行政区划调整过而项目里的city_code.json没有同步。原因是编码表过期不是爬虫逻辑出错。解决方法是跑一遍tools/update_city_code.py它会从公开统计页面拉取最新行政区划并重新生成编码表。如果没有同步接口只能人工对照。说到底城市编码表是天气爬虫里最容易过期的部分建议每次发版前都强制跑一次更新脚本我后来养成的习惯是每个季度手动核对一次增量。5.3 画面SQLite 表数据重复膨胀去重失效同一天同一城市出现了两条记录查了 Redis 发现连接在某一次请求时断掉了is_fetched函数的异常处理直接返回 False导致后面的请求全部重新抓取入库。原因是单层去重失效Redis 不可用时没有兜底方案。解决方式是在存储层加一道保险给表建UNIQUE(city, date)联合索引。这样即使 Redis 完全宕机INSERT OR REPLACE也会按唯一索引覆盖旧数据不会产生重复记录。这是典型的血泪经验——任何一层去重都可能失效所以要在最底层的存储处做最终兜底。5.4 现象中文全部变成“锟斤拷”页面返回时 requests 自动把响应编码猜成 ISO-8859-1导致中文乱码。原因是响应头里的 charset 声明缺失requests 的自动判断逻辑就会出错。实际修复很简单在 fetch 里显式设置resp.encoding utf-8或者拿到文本后手动做一次 decode从根本上绕过自动判断的不确定性。resp requests.get(url, headersHEADERS, timeoutTIMEOUT) resp.encoding utf-8 # 显式指定不依赖响应头声明 return resp.text这段代码与前面 fetcher 中的写法一致关键是不依赖响应头的 charset 声明直接按项目使用场景里最常见的编码来定。如果遇到极端场景是 GBK 页面再按情况调整即可。编码问题是爬虫里最隐蔽的坑因为它不报错只让数据看起来像乱码。5.5 现象解析出来的字段全是空值某次采集跑完后入库记录里城市名正常但温度、风力字段全是空字符串。原因是目标站改版表格的列顺序从“高低温、天气、风力”换成了“天气、风力、高低温”parser 按旧坐标取列自然拿不到正确内容。排查思路是先看原始 HTML把 fetcher 返回的文本存成文件对比 XPath 命中的节点内容就能看出列顺序是否变化。解决方式是把 parser 里的字段坐标改成按表头文字匹配先读出表头行再根据表头定位列索引。这个改动会让解析器更健壮也是我在后续二次开发中优先建议做的一步。6. 二次开发把“当天天气数据集”改造成“按城市订阅的监控告警”面向二次开发这个项目的最佳切入点是把全量批量采集改造成“只关注特定城市的订阅式采集”。具体做法是新增一个 watchlist 模块在 runner 主循环里对每个城市做一次订阅过滤# 在 run() 主循环中插入订阅过滤逻辑 WATCHLIST [city_a, city_b] # 改成自己关心的城市编码 def should_collect(city_code: str) - bool: return city_code in WATCHLIST改造的价值在于原来是“采全国回来再筛选”现在是“只采订阅城市”请求量、存储量和反爬压力都直降一个量级。我一般会把 WATCHLIST 放到配置文件里用 JSON 读入方便业务人员自行增删城市不用改代码。如果团队有多个人维护这个设计还能避免误改源码里的编码列表。除了订阅过滤另一个值得动刀的地方是数据输出格式。项目默认落 SQLite但监控告警场景下需要方便对接消息推送。我习惯在 storage.py 里加一个export_latest_to_json函数把最新一天的数据整理成 JSON 数组并排除空字段记录。这样后续无论是写日志、推群消息还是做可视化都能直接消费同一份数据。回归验证时有两个小技巧。一是用一个固定的小城市列表跑一次全流程然后人工核对几个城市的气温字段确认与目标页面显示一致二是对同一城市连续抓两次验证daily模式确实覆盖写而非新增记录。如果改造过程中动了 parser还要额外验证字段坐标把原始 HTML 保存一份用改动前后两版 parser 分别解析对比字段值是否完全一致。我从这个项目里学到的习惯是每一次改造结束都要先跑一个最小数据集确认链路没断再放大到全量。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Superpowers:AI原生开发者的智能编程辅助工具链集成范式

Superpowers:AI原生开发者的智能编程辅助工具链集成范式

1. 项目概述:Superpowers 不是超能力,而是开发者工具链的“认知增强层”最近在好几个技术群和开源社区里,频繁看到“Superpowers”这个词被反复提起——不是漫威电影里的变种人设定,也不是某个新出的AI模型代号,而是一…

📅 2026/10/17 12:34:40
Mybatis-Plus条件构造器、自定义SQL与Service接口核心用法实战解析

Mybatis-Plus条件构造器、自定义SQL与Service接口核心用法实战解析

SpringCloud 系列教程:微服务的未来(二)Mybatis-Plus的条件构造器、自定义SQL、Service接口基本用法做微服务开发,跟数据库打交道是绕不开的日常。Spring Cloud 体系里服务拆分之后,每个服务都要管好自己的数据&#x…

📅 2026/10/17 12:34:40
Visual Studio一键化C++开发:CMake与vcpkg构建自动化实践

Visual Studio一键化C++开发:CMake与vcpkg构建自动化实践

1. 为什么需要一套“一键化”流程:从手动编译的痛点说起1.1 大多数团队的开发流程到底卡在哪我接手过不少类似 OpenClaw 风格的项目——源码结构不大复杂,但每次从拉取代码到真正跑起来,中间隔着七八个手工步骤:先要安装依赖、配置…

📅 2026/10/17 12:34:40
MORE NEWS

更多资讯

📰

dpc++(oneAPI)调用nvidiaGPU配置与验证:把Base URL改到TaoToken

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

📰

mac本地部署大模型:oMLX + open claw 的 Base URL 改到 TaoToken 实践

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

📰

汇编MOV指令数据流向全解:从寻址方式到调试实战

如果你写过几行汇编,大概会觉得 MOV 是一天中最“没有悬念”的一条指令:不就是把数据从右边搬到左边吗?但等你真的在调试器里追数据追到怀疑人生,或者面对带各种寻址、宽度、来源与限制的组合时,才会发现,M…

📰

国内用户友好的AI Code Agent搭建与调优实践

1. 为什么我会想自己搭一个"国内用户友好的 AI Code Agent"先说说背景。前两年各种 AI 编程助手满天飞,我也跟风充过几个国际大厂的会员,能力确实强,但用下来总有几个绕不开的别扭点:网络请求时好时坏、代码补全区经常性…

📰

改进YOLOv5实现膝关节骨关节炎X光自动分级:从定位到分类的工程实践

1. 项目整体设计思路:为什么要拿YOLOv5来搞骨关节炎分级膝关节骨关节炎(Knee Osteoarthritis,简称KOA)的X光影像分级,在临床上长期依赖医生肉眼判读,按Kellgren-Lawrence(KL)标准分成…

📰

大模型微调全流程指南:从LoRA选型到部署实战

这几周在好几个技术社群里看到同样一个问题:为什么我用了开源大模型做垂直领域的问答,效果还是差强人意?有让它理解某个行业术语的,有想让模型学会特定文风的,也有希望模型能根据自家产品知识库说话的。问题五花八门&a…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬