news 2026/10/1 12:00:11

基于Spring Boot+Vue的宿舍水电费报修管理系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Spring Boot+Vue的宿舍水电费报修管理系统设计与实现

1. 项目整体设计与技术选型思路

1.1 核心需求解析:宿舍管理员到底想要什么

做这个系统之前,我特地去和几位高校后勤的老师聊过,发现大家的需求高度一致:宿舍水电费核算太麻烦、报修进度全靠微信群吼、月底对账更是让人头大。

传统的管理方式是每个月底抄表员挨个宿舍抄电表水表,回到办公室用 Excel 登记,再手工计算每间宿舍的费用,最后把账单贴在宿舍楼下。一旦遇到有学生报修,还得打电话催维修师傅,修没修好、什么时候修的,全靠口头沟通。一套流程走下来,不仅效率低,还容易产生纠纷——学生说热水器坏了没人管,维修师傅说早就修好了,双方各执一词,因为没有留痕。

所以我给这个"学生宿舍水电费报修管理系统"定的核心目标很明确:把水电费计算、报修流程、宿舍信息管理三件事全部线上化,并且每一条操作都有记录可追溯。系统面向三类用户:学生(查看自己宿舍的水电用量与费用、提交报修、跟踪进度)、宿管/管理员(录入抄表数据、设置单价、指派维修师傅、审核报修结单)、系统管理员(管理宿舍楼栋、房间、用户账号、角色权限、数据统计)。

1.2 为什么选 Spring Boot + Vue 前后端分离

现在做管理系统,技术选型上其实有不少方案。我最终确定用 Spring Boot 做后端、Vue 做前端,核心考量有三点。

第一是团队协作效率。前后端分离之后,前端小组专心写页面交互,后端小组专心写接口和业务逻辑,两边只需要约定好接口文档就能并行开发。这个项目里我估算了一下,如果做单体 JSP 项目,页面和后端代码混在一起,一个人改页面另一个人就得等他;分离之后整个开发周期至少缩短三分之一。

第二是Spring Boot 的开发效率确实高。自动装配机制省掉了大量 XML 配置,内置 Tomcat 让项目可以一键启动。配合 Spring Data JPA 或者 MyBatis-Plus,连建表到实体映射的工作都简化了。再加上 Spring Security 做登录鉴权,RBAC 权限模型几行配置就能落地,非常适合这种中小型管理系统。

第三是Vue 的组件化开发太适合表单密集型场景了。水电费管理系统的页面大量集中在"表格 + 表单弹窗 + 详情抽屉"这三种形态,Vue 的单文件组件可以把每一块 UI 拆成独立组件复用。比如水费录入表格组件、报修工单状态标签组件,在多个页面里直接引用,维护成本低。

还有一个现实因素:这个项目是典型的教学/毕设/练手项目场景。Spring Boot + Vue 是目前市面上资料最多、遇到问题最容易搜到解决方案的组合,招人门槛也低。换个冷门框架,光踩坑就能劝退不少人。

2. 数据库设计与核心模块拆解

2.1 数据库表结构规划:九张表覆盖全部业务

先把表结构讲清楚,这是整个系统的地基。我按照业务域拆分成三类:

用户与组织域:用户表(user)、宿舍表(dormitory)、楼栋表(building)。这里的核心设计思路是用户和宿舍做关联,学生用户通过"宿舍ID"字段关联到具体的房间;楼栋表则是宿舍表的上层组织,方便按楼栋做数据统计和权限隔离。

费用业务域:电费记录表(electricity_record)、水费记录表(water_record)、缴费单表(payment_order)。水电记录表是用来存放每一次抄表数据的,缴费单表则负责生成学生需要支付的账单。

报修业务域:报修工单表(repair_order)、报修类型表(repair_category)、操作日志表(operation_log)。

下面给一张精简的核心表设计参考(字段只列关键项):

表名关键字段用途说明
userid, username, password(BCrypt), role, dormitory_id存储三类账号,role 区分 student / admin / root
buildingid, name, manager_name楼栋基础信息
dormitoryid, building_id, room_no, bed_count房间信息,bed_count 用于按人均摊水电费
electricity_recordid, dormitory_id, month, last_reading, current_reading, unit_price, amount每月电费抄表数据,amount 由度数乘以单价计算
water_recordid, dormitory_id, month, last_reading, current_reading, unit_price, amount同电费,单位按吨计
payment_orderid, user_id, dormitory_id, order_no, total_amount, status(0/1), pay_time缴费单,状态 0 未缴 1 已缴
repair_orderid, dormitory_id, reporter_id, category_id, description, images, status(0-4), assignee, finish_time报修工单,状态机下面细讲
repair_categoryid, name, response_timeout报修类型,比如水龙头、电路、门窗
operation_logid, user_id, action, detail, create_time关键操作留痕

有一个容易被忽略但很重要的设计点:抄表记录里必须同时存上次读数和本次读数,而不是只存本次度数。这样做的目的是可追溯、可复核。学生质疑"这个月度数怎么这么高"时,管理员可以直接看到上月底的底数和这个月底的底数,还能去现场复核表具,避免纠纷。

2.2 水电费计费逻辑:阶梯计价与均摊算法

水电费计算是这个系统的核心业务,计价逻辑不能拍脑袋写死。我在设计时预留了两种计费模式:固定单价模式和阶梯计价模式。

固定单价就是每度电多少钱、每吨水多少钱,直接用(本次读数 - 上次读数) * 单价计算。这个是基础。

阶梯计价稍微复杂一点,需要考虑"用量区间"。比如规定每间宿舍每月基础用电额度是 30 度,30 度以内按 0.5 元/度,超过部分按 0.8 元/度。计算逻辑是:

基础部分:min(用量,阶梯阈值) * 第一档单价 超出部分:max(用量 - 阶梯阈值,0) * 第二档单价 合计金额 = 基础部分 + 超出部分

用实际数字演示一下:某宿舍本月用电 42 度,第一档 30 度 0.5 元,第二档 12 度 0.8 元,那么费用 = 30×0.5 + 12×0.8 = 24.6 元。

阶梯阈值和单价我建议放在系统配置表里,不要硬编码在代码中,这样换一届后勤领导调价时,管理员在后台改一下配置就行,不用重新发版。

人均均摊也是一个高频需求。学校宿舍一般按宿舍为单位计费,但有的学校要求按床位分摊到个人。实现方式是 dormitory 表的 bed_count 字段参与计算:人均费用 = 宿舍总费用 / bed_count。缴费单表再把人均费用关联到每个学生的 user_id 上。

这里有一个经验之谈:水电费计算建议做成月度定时任务批量生成,而不是学生在页面上点击"查询"时才实时计算。原因是实时计算会在高峰期造成数据库压力,而且容易受抄表数据未录入的影响生成错误账单。我通常搭配 Spring 的 @Scheduled 定时注解做每月 1 号凌晨自动结算,生成当月所有宿舍的缴费单。

3. 后端核心接口实现与权限控制

3.1 Spring Boot 项目初始化的关键配置

项目骨架我用的是 Spring Initializr 生成,Java 版本选 8 或 11 都没问题,Spring Boot 版本建议选 2.7.x 而不是 3.x。为什么?因为国内大量教程、博客、毕业设计参考代码基于 2.x 版本,javax.servlet 命名空间和 3.x 的 jakarta.servlet 有兼容性差异,一旦用到一些老版本的工具类或代码片段,在 3.x 下会直接编译失败。选 2.7.x 能最大化减少折腾时间。

依赖方面,核心就五个:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>

JPA 和 MyBatis-Plus 二选一就可以。JPA 的优势是实体类之间关联关系清晰,自动建表省心;MyBatis-Plus 的优势是复杂 SQL 写起来更顺手、代码生成器可以一键生成 CRUD。我个人在这个项目里用了 JPA,因为表关联嵌套关系多(楼栋→宿舍→账单),用注解映射比手写 SQL 直观。

application.yml 里有一个关键配置必须处理——时间字段的时区问题。MySQL 默认时区是 UTC,中国是 UTC+8,不设置的话时间字段会差 8 小时。我的配置习惯是:

spring: datasource: url: jdbc:mysql://localhost:3306/dormitory_system?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 jpa: hibernate: ddl-auto: update show-sql: true

ddl-auto: update在开发阶段确实方便,实体类改一个字段自动同步到表结构,但上线前一定要改成validate或者直接关闭自动改表,否则不小心删掉字段可能导致数据丢失。

3.2 报修工单状态机设计与流程流转

报修模块最容易做成一坨"散装代码",就是单纯更新 status 字段,没有任何流程约束。学生可以随意改状态,管理员也不知道该处理哪一步。

我给报修工单定义了一个五状态流转模型:

状态值状态名称说明进入条件
0待受理学生刚提交学生提交报修
1已受理(待维修)管理员审核通过并指派维修师傅管理员点击"受理"
2维修中维修师傅标记开始维修师傅点击"开始维修"
3已完成待确认维修师傅提交完成师傅点击"完成维修"
4已确认关闭学生确认维修结果学生点击"确认"

状态流转图(文字描述)就是:0→1→2→3→4,任何一个环节学生都可以点击"取消报修"直接置为关闭状态。不能跳步骤,比如从 0 直接跳 3 是禁止的。

后端实现时我用了一个状态机校验工具方法,核心代码如下:

private static final Map<Integer, List<Integer>> TRANSITIONS = new HashMap<>(); static { TRANSITIONS.put(0, Arrays.asList(1, 4)); // 待受理可流转到 已受理 或 已关闭 TRANSITIONS.put(1, Arrays.asList(2, 4)); TRANSITIONS.put(2, Arrays.asList(3, 4)); TRANSITIONS.put(3, Arrays.asList(4)); } public void transition(RepairOrder order, int targetStatus) { List<Integer> allowed = TRANSITIONS.get(order.getStatus()); if (allowed == null || !allowed.contains(targetStatus)) { throw new IllegalStateException("非法状态流转: " + order.getStatus() + " -> " + targetStatus); } // 权限校验:学生只能提交/取消/确认,管理员只能受理/指派 order.setStatus(targetStatus); if (targetStatus == 3) { order.setFinishTime(LocalDateTime.now()); } }

这个设计的价值在于:非法操作在业务层就被拦截,而不是等到数据库出异常。前端下拉框能选的选项和后端校验规则保持一致,学生也钻不了空子。

3.3 金额计算精度与并发扣费问题

水电费涉及金额,两个常见的坑必须提前处理。

第一个坑是小数精度。Java 里直接用 float/double 计算金额,0.1×3 的结果可能是 0.30000000000000004。虽然单笔差异小,但多笔累加之后误差会被放大,对账的时候就会对不上。正确做法是金额字段用 BigDecimal,数据库层面用 decimal 类型。

BigDecimal amount = new BigDecimal(degree) .multiply(new BigDecimal(unitPrice)) .setScale(2, RoundingMode.HALF_UP);

第二个坑是并发扣费。学生可能同时用电脑和手机登录账号,两个设备都在缴费页点击"确认支付"。如果代码只做了"查询订单状态→如果未支付则更新为已支付"两步操作,在高并发下可能出现两个请求同时读到"未支付",然后都执行更新,最终一个订单被扣两次。

解决办法是在数据库层面加乐观锁。在 payment_order 表加 version 字段:

@Version private Integer version;

更新 SQL 变成UPDATE payment_order SET status=1, version=version+1 WHERE id=? AND version=?。第二个请求进来时版本号已经变了,更新影响行数为 0,直接提示"订单已处理,请勿重复操作"。这是我强烈建议任何涉及"确认支付"类业务都必须加的兜底方案。

4. 前端 Vue 页面设计与联调

4.1 项目搭建:Vue CLI 还是 Vite?

创建前端项目时我遇到了选型问题,最后用了 Vite。原因很简单:Vite 冷启动速度比 Webpack 快一个量级,而且内置了对 Vue 3 的一等支持。项目开发时改一个组件文件,热更新几乎是秒级,体验非常好。

创建命令也很简单:

npm create vite@latest dormitory-web -- --template vue cd dormitory-web npm install npm install vue-router@4 pinia axios element-plus

UI 组件库方面,我选的是 Element Plus。这个项目需要的表格、表单、步骤条、弹窗组件它都有现成的,而且风格统一,不需要额外调 CSS。大体量的管理系统别自己造 UI 轮子,费时费力还容易出样式 bug,直接站在组件库的肩膀上写业务逻辑才是正解。

项目目录结构我按"页面 + 组件 + 请求封装 + 路由 + 状态管理"五层组织:

src/ api/ // 按模块封装 axios 请求(user.js、repair.js、bill.js) assets/ // 静态资源 components/ // 可复用组件(DormitorySelect、StatusTag、BillTable) router/ // 路由配置文件 store/ // Pinia 状态管理(用户信息、当前宿舍) views/ student/ // 学生端页面:费用查询、报修提交、报修进度 admin/ // 管理端页面:抄表录入、工单处理、账单管理 layout/ // 布局容器

请求封装这一块值得多说两句。axios 实例要统一设置拦截器,请求拦截器注入 token,响应拦截器统一处理业务错误码和 401 跳转。否则每个页面都得写一遍"取 token → 塞请求头 → 判断状态码 → 处理异常"的逻辑,代码会非常冗余。

import axios from 'axios' import { ElMessage } from 'element-plus' import router from '@/router' const service = axios.create({ baseURL: '/api', timeout: 10000 }) service.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers['Authorization'] = `Bearer ${token}` } return config }) service.interceptors.response.use( response => { const res = response.data if (res.code === 200) { return res } ElMessage.error(res.msg || '请求失败') return Promise.reject(new Error(res.msg)) }, error => { if (error.response?.status === 401) { router.push('/login') } ElMessage.error(error.message || '网络异常') return Promise.reject(error) } )

4.2 核心页面交互细节:抄表、报修、缴费三块硬骨头

抄表录入页面是最简单也最容易做难用的。管理员的真实使用场景是:拿着抄表本,一个一个宿舍录入数据,动作重复且枯燥。所以这个页面的核心交互诉求是"少点几下、少切几次输入框"。

我的处理方式是用 Element Plus 的 el-table 配合行内编辑:

  • 页面默认展示所有宿舍的列表,每行包含"上次读数","本次读数"两个输入框,数字输入框自动聚焦,回车或 Tab 跳到下一行。
  • 每行输入完自动计算用量和金额,实时展示在行尾,管理员可以边抄表边核对数是否合理(比如某宿舍用电量突然飙到 200 度,当场就能发现异常)。
  • 最后统一点击"保存本月抄表",后端批量插入记录并预生成缴费单。

报修提交页面的重点是富交互:学生提交时要选择报修类型、填写描述、上传图片(拍摄漏水部位或损坏的插座)。图片上传我用的 Element Plus 的 el-upload 组件,后端配合一个上传接口,把文件存到本地服务器或者 MinIO 对象存储,回传 URL 存到工单表的 images 字段。

这里有一个交互细节,报修单详情页一定要有个时间线组件(el-timeline),把"提交时间→受理时间→开始维修时间→完成时间→确认时间"全部展示出来。学生看到时间线就会觉得流程透明,减少催单焦虑;管理员也能一眼看出哪个环节卡住了,方便督办。

缴费页面要注意的是:查询账单接口返回金额时必须使用字符串而不是数字。因为金额超过一定位数时,JavaScript 的 Number 精度会丢失,虽然水电费单笔金额不大,但统计报表里的总金额字段可能达到百万级别,还是可能踩精度坑。前端展示直接用 BigDecimal.toPlainString() 返回的字符串,避免任何中间转换运算。

4.3 路由权限控制:不同角色看到不同菜单

管理系统必须做菜单级权限控制,不然学生登录后能看到"抄表录入"菜单就闹笑话了。

路由配置我采用了"静态路由 + 动态路由"结合的方式:

  • 静态路由只包含 /login、/404、/layout 框架页。
  • 用户登录成功后,后端根据角色返回该角色可访问的菜单列表和路由组件名,前端用 router.addRoute 动态添加路由。

组件映射这里有个小坑:前端提前用 import.meta.glob 预注册所有页面组件,否则动态路由加载时无法匹配组件。写法如下:

const viewModules = import.meta.glob('../views/**/*.vue') export function buildRoute(menu) { return { path: menu.path, name: menu.name, component: viewModules[`../views/${menu.component}.vue`], meta: { title: menu.title, icon: menu.icon } } }

Vite 的 glob 导入在构建时会扫描文件,把匹配的组件打包进产物,运行时通过 key 直接取组件对象,不会出现"找不到模块"的问题。

5. 常见问题与排查技巧实录

5.1 跨域问题:前后端联调第一道坎

开发环境前端跑在 5173 端口,后端跑在 8080 端口,直接请求必然跨越。我有两种解决方式,开发阶段推荐用 Vite 的 proxy 代理,生产环境推荐用 Nginx 反代。

Vite 代理配置(vite.config.js):

export default defineConfig({ server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, rewrite: path => path.replace(/^\/api/, '') } } } })

前端请求 /api/login 时,Vite 会把请求转发到 http://localhost:8080/login,CORS 问题完全规避掉。注意后端接口不要写 /api 前缀,否则 rewrite 掉前缀后会路径不匹配。

后端如果确实需要开启跨域(比如某些客户端绕过代理直连后端),可以在 Spring Boot 里配置全局 CORS:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600); } }

配置跨域后如果前端还报跨域错误,优先检查请求是不是 OPTIONS 预检没过,比如 allowedHeaders 没加 Authorization。

5.2 Spring Boot 版本过高引发的编译报错

在一台电脑上新建项目,依赖自动下载了 Spring Boot 3.2.x,结果一跑就报错。检查发现是引用的 jjwt 0.9.1 在 jakarta 命名空间下无法识别 javax.crypto 相关的类,直接编译失败。

这里给大家两个处理思路:

  • 方案一(推荐):手动把 Spring Boot 版本降级到 2.7.x。在 pom.xml 里spring-boot-starter-parent的 version 明确写 2.7.18,之后 IDE 会自动重新下载对应依赖。
  • 方案二:把 jjwt 替换成新版 0.12.x,并将javax.servlet相关的代码改成jakarta.servlet。但 JPA、Security 的相关 API 在 Spring Boot 3.x 里也有变化,改动量比较大。

我的经验是:非必要不上 Spring Boot 3.x。除非你有虚拟线程、GraalVM 这类新特性的明确需求,否则现有业务系统 2.7.x 完全够用,而且生态兼容性更好。

5.3 Vue 页面数据不更新的疑难杂症

Vue 3 用了 Proxy 响应式,但依然有"数据改了,页面不刷新"的情况。最常见的原因是对象新增属性或者数组按下标赋值。

比如我从后端拿到账单列表后,需要给每个对象临时加一个 selected 属性用于勾选:

// 错误写法 res.data.forEach(item => { item.selected = false })

这样写 Vue 的响应系统检测不到新属性,页面绑定 selected 后不会生效。正确写法是用 reactive 或者 ref 把整个数组先包成响应式:

const tableData = ref([]) const loadData = async () => { const res = await getBillList() res.data.forEach(item => { item.selected = false }) tableData.value = res.data }

因为 tableData.value 整体被重新赋值了,Vue 的响应式系统会重新解析整个数组,新属性也被代理到。如果用 el-table 勾选列不生效,多半就是这个原因,把整个数组重赋值一次就能解决。

5.4 时间和金额显示问题速查表

症状根因解决方案
创建时间显示比实际晚 8 小时数据库连接串未设置 serverTimezoneJDBC URL 显式加 serverTimezone=Asia/Shanghai
前端显示时间格式混乱后端返回 LocalDateTime 序列化为数组全局配置 Jackson 日期格式化,返回 yyyy-MM-dd HH:mm:ss
金额累加结果有误差使用 double/float 计算金额统一 BigDecimal,除法指定精度和舍入模式
金额显示过长小数BigDecimal 未设置 scalesetScale(2, RoundingMode.HALF_UP)
前端金额精度丢失后端返回数字类型后端转字符串返回,前端只做展示不做运算

6. 实操心得与扩展建议

整个系统从零到落地,前后大概花了三周时间。要是让我重新做一遍,第一件事一定是先把状态机和金额精度问题理清楚,而不是一上来就开始写 CRUD——这两个问题在项目后期返工的成本最高。

前端联调阶段最值得投入时间的是接口文档。我推荐直接用 Apifox 或 Swagger 生成在线接口文档,前端不用反复问后端"这个字段啥意思",后端不用反复解释"你传的是 JSON 还是 FormData"。团队协作效率提升非常明显。

这个系统后续还有几个可以扩展的方向,供大家参考:

  • 接入校园一卡通或微信支付,缴费单生成后直接在线支付,省掉线下收费环节。
  • 加入宿舍评分模块,把报修响应速度、宿舍卫生检查结果汇总成评分,和文明宿舍评比联动。
  • 用 ECharts 做能耗趋势分析,按楼栋、按月展示水电用量曲线,帮助后勤部门发现异常能耗(比如某栋楼深夜用水异常,可能存在漏水)。

最后分享一个我在实际项目里坚持的习惯:把抄表录入和缴费结算的权限分开。录入数据的人不能同时审核账单,至少要在系统里区分两个管理员角色,哪怕实际只有一个人管理,也要预留这个权限边界。这样万一出现数据错误,追溯流程是清晰的,不会出现"自己录错、自己确认、自己背锅"的局面。系统再小,权限设计的底线不能丢。

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

Linux运行Excel VBA宏:Wine、虚拟机、兼容层与Python重写

上周有个做运营报表的朋友甩给我一个 3MB 的.xlsm文件&#xff0c;里面塞了两千多行 VBA&#xff0c;干的事情是每天把三个部门的明细表跑一遍 SUMIFS、生成一张甘特图、再导出一份带格式的汇总表。问题是他整套工作流已经搬到 Linux 上了&#xff0c;服务器是国产 Linux 发行版…

作者头像 李华
网站建设 2026/10/1 11:59:49

ARM汇编CMP指令原理与实战:标志位、条件执行与跨架构避坑

1. CMP指令到底在ARM汇编里干啥&#xff1f;别再把它当成“比较就完事”的黑盒了你写ARM汇编时&#xff0c;是不是经常看到CMP R0, #5、CMP R1, R2这类指令&#xff0c;顺手就抄进代码里&#xff0c;然后靠BEQ、BNE跳转收尾&#xff1f;我刚入行那会儿也是——直到有次调试一个…

作者头像 李华
网站建设 2026/10/1 11:59:41

Univer在线表格实战:用命令拦截实现单元格只读与可编辑区域控制

1. 为什么选Univer做在线填报表格&#xff1a;场景与选型分析 1.1 一个很常见的需求&#xff1a;表格能看&#xff0c;但不能随便改 先说我手上这个项目。甲方要做一个报表平台&#xff0c;其中一个核心功能是&#xff1a;运营人员从后台选择一张报表模板&#xff0c;模板里已…

作者头像 李华
网站建设 2026/10/1 11:59:23

MATLAB高斯光束到平顶光束整形:GS算法与SLM相位分布计算

我一直觉得&#xff0c;光束整形是光学实验里“看起来简单、做起来全是细节”的典型课题。这篇东西聊的是用MATLAB实现高斯光束到平顶光束的转变&#xff0c;核心手段是GS算法和直接计算SLM相位分布这两条路。简单说&#xff0c;就是激光器出来的光斑强度是中间亮、边缘暗的高斯…

作者头像 李华
网站建设 2026/10/1 11:59:23

Python爬虫进阶:反爬突破与效率优化的实战经验

我最早写爬虫的时候&#xff0c;跟大多数新手一样&#xff0c;以为只要会 requests.get(url) 再加个解析就完事了。直到第一次写一个招聘网站的采集脚本&#xff0c;刚跑不到五分钟&#xff0c;对方直接弹了 403&#xff0c;紧接着 IP 被封了十分钟。那一刻我才意识到&#x…

作者头像 李华
网站建设 2026/10/1 11:58:58

EfficientNet迁移学习实战:104种花卉图像分类与模型微调指南

简介&#xff1a;这是一套面向图像分类实战的EfficientNet迁移学习工程&#xff0c;重点解决104种常见花卉的自动识别&#xff0c;适合希望从零开始掌握迁移学习、完成自定义分类项目的开发者。包内共2000个文件&#xff0c;以1993张花卉样本jpg为主&#xff0c;另有3个Python训…

作者头像 李华