Django+Python影城售票系统:从数据建模到并发锁座的完整实战
做这个项目的人我见过不少各种课设、毕设、还有想转行拿来做作品集的但说实话十个里有八个做的只是“换皮图书管理系统”——能增删改查电影和场次再让用户注册登录然后就没然后了。前阵子我帮人改造一个类似的模拟项目X改到订单状态和座位锁定时才真正体会到影城售票系统最值钱的部分从来不是CRUD而是那套业务规则和流程约束。所以这篇我想聊透的是如果你真的打算用Django Python从零写一个能跑的影城售票管理系统到底该把劲往哪使。我会按我实际改造项目的顺序来拆——业务边界、数据建模、售票主流程、权限设计、部署上线把真正会翻车的细节一个个摆出来。适合有一定Python基础、想系统掌握Django MTV架构的人也适合正在用这个题目做课设但不想只交个玩具上去的同学。1. 影城售票系统真正难在哪先盘清业务边界1.1 为什么“售票”比“图书管理”复杂一个量级很多新手拿到这个题目第一反应是不就是电影、场次、订单三个表吗我告诉你这个想法就已经埋雷了。图书管理系统的核心是库存数量你减一个数字就行售票系统不一样它卖的是“某一个影厅里、某一个场次、某一个具体座位”的座位状态这是三维的。再叠加几个特性订单牵扯钱不能乱改座位有并发抢占用户同时选同一个座位的场景必须处理订单有生命周期待支付、已支付、已取消、已退票状态之间不能乱跳。这三个特性叠加起来天然比图书管理高一个难度等级。所以第一步不是写代码而是把系统到底要做成什么样、边界划在哪想清楚。1.2 核心模块拆分与取舍我帮人改造时习惯先列一张模块清单确定哪些是主链路、哪些是附属避免后面越写越乱。一个基础能跑的影城售票系统最少要有六块模块核心职责缺了它会怎样用户模块注册、登录、身份角色没法区分普通观众和员工电影模块影片信息维护、上映状态场次没有载体影厅与座位模块影厅布局、座位物理归属无法定义“你在几排几座”场次模块某影厅某时间放某电影无法形成可售票资源订单与票模块锁定座位、生成订单、门票核心卖票链路断裂后台管理排片、定价、核销、数据查看运营没法使用系统至于会员积分、优惠券、退改签、自动取票机对接这些都属于扩展项。我做基础版时建议先砍掉等主链路彻底跑通了再往上加。优先级不排好很容易写着写着就把自己绕进了一个优惠分摊的计算逻辑里核心的并发处理反而没时间打磨。1.3 角色与权限粗模型影城售票系统不是只有用户和Admin两级。真实场景里至少有四类角色普通观众负责买票前台员工负责现场售票、退票、入场核销运营人员负责排片和调价系统管理员负责用户和基础数据。Django自带User和Group天然适合做这个事后面我会专门讲权限怎么落地。现在你只要记住需求阶段就把角色区分开别等代码写完了再回来补。2. 数据建模是命根子Django模型设计的取舍与反例2.1 核心模型逐个拆解数据模型决定了系统能走多远我见过太多项目因为表设计问题推倒重来。下面是经过实际验证的一套模型方案每个字段我都写清楚为什么这么定。from django.db import models from django.contrib.auth.models import AbstractUser from django.utils import timezone class User(AbstractUser): phone models.CharField(max_length20, blankTrue) # 不额外建Profile表直接扩展User是小型项目最省事的方式 class Movie(models.Model): title models.CharField(max_length200, verbose_name片名) poster models.ImageField(upload_toposters/, blankTrue, verbose_name海报) duration models.PositiveIntegerField(verbose_name时长(分钟)) release_date models.DateField(verbose_name上映日期) language models.CharField(max_length50, blankTrue) version models.CharField( max_length20, choices[(2d, 2D), (3d, 3D), (imax, IMAX)], default2d ) description models.TextField(blankTrue) def __str__(self): return self.title class Hall(models.Model): name models.CharField(max_length50, verbose_name影厅名) rows models.PositiveIntegerField(verbose_name排数) cols models.PositiveIntegerField(verbose_name列数) def __str__(self): return self.name class Seat(models.Model): hall models.ForeignKey(Hall, on_deletemodels.CASCADE, related_nameseats) row models.CharField(max_length5, verbose_name排号) col models.PositiveIntegerField(verbose_name列号) class Meta: unique_together (hall, row, col) def __str__(self): return f{self.hall.name}-{self.row}排{self.col}座 class Session(models.Model): movie models.ForeignKey(Movie, on_deletemodels.CASCADE, related_namesessions) hall models.ForeignKey(Hall, on_deletemodels.CASCADE, related_namesessions) start_time models.DateTimeField(verbose_name开场时间) price models.DecimalField(max_digits6, decimal_places2, verbose_name票价) class Meta: unique_together (hall, start_time) def __str__(self): return f{self.movie.title} {self.start_time:%Y-%m-%d %H:%M} class SessionSeat(models.Model): AVAILABLE 0 LOCKED 1 SOLD 2 STATUS_CHOICES [ (AVAILABLE, 可售), (LOCKED, 锁定), (SOLD, 已售), ] session models.ForeignKey(Session, on_deletemodels.CASCADE, related_nameseat_status) seat models.ForeignKey(Seat, on_deletemodels.CASCADE) status models.PositiveSmallIntegerField(choicesSTATUS_CHOICES, defaultAVAILABLE) class Meta: unique_together (session, seat) indexes [ models.Index(fields[session, status]), ] def __str__(self): return f{self.seat} - {self.get_status_display()} class Order(models.Model): PENDING 0 PAID 1 CANCELLED 2 REFUNDED 3 STATUS_CHOICES [ (PENDING, 待支付), (PAID, 已支付), (CANCELLED, 已取消), (REFUNDED, 已退款), ] order_no models.CharField(max_length32, uniqueTrue, verbose_name订单号) user models.ForeignKey(User, on_deletemodels.PROTECT, related_nameorders) session models.ForeignKey(Session, on_deletemodels.PROTECT) amount models.DecimalField(max_digits8, decimal_places2) status models.PositiveSmallIntegerField(choicesSTATUS_CHOICES, defaultPENDING) created_at models.DateTimeField(auto_now_addTrue) paid_at models.DateTimeField(nullTrue, blankTrue) class Ticket(models.Model): order models.ForeignKey(Order, on_deletemodels.CASCADE, related_nametickets) session_seat models.OneToOneField(SessionSeat, on_deletemodels.PROTECT) check_code models.CharField(max_length20, uniqueTrue)这套模型里有几个地方是反复踩坑后才确定的下面单独讲。2.2 座位设计的两种方案为什么我选了中间表座位的物理归属是个容易争议的点。一种做法是把Seat直接挂在Session下每个场次复制一套座位另一种是把Seat挂在Hall下场次需要卖票时再动态判断。第一种的缺点是影厅的座位布局一旦调整历史所有场次数据全乱第二种好一些但你没法直接记录“这个场次这个座位被谁锁了”。所以我最终选了第三种变体Seat挂在Hall表示物理座位SessionSeat作为场次和座位之间一张中间表专门记录每个场次下每个座位的售卖状态。加一场排片时自动为这场生成Hall下所有座位的SessionSeat记录订票时只改SessionSeat的statusSeat本身不动。这样影厅座位改一次所有场次跟着生效历史数据也不会歪。2.3 订单状态为什么要用IntegerField而不是一堆布尔字段我见过有人用is_paid、is_cancelled、is_refunded三个布尔字段表示订单状态看起来直观实际用起来全是坑。典型问题一张订单即is_paidTrue又is_cancelledTrue这种数据在系统里到底算什么非法状态就这么轻轻松松产生了。订单状态是典型的状态机用IntegerField choices枚举才是正经做法。Django的choices约束虽然只是“限制输入值”不是数据库级别的严格约束但配合代码约定和定期巡检完全够用。更重要的是在代码里凡是涉及状态变更都走同一个方法逻辑就统一了。我还建议把状态变更记录到一张单独的OrderLog表里这样出现问题时能追溯运营和运维都会感谢你。2.4 外键与索引哪些会影响真实查询性能平时写着玩你可能感觉不到索引的存在但一旦一个场次的SessionSeat达到两三百条记录、订单量上万查询性能就藏不住了。我在改造时至少加了三个关键点第一SessionSeat的unique_together(session, seat)保证同样的场次座位不重复天然防插入脏数据第二为SessionSeat加了一个包含sessionstatus的联合索引因为“查某场次哪些座位可售”是所有售票场景最高频的查询第三Order的order_no字段必须唯一这是业务层面找订单的唯一凭据不要用主键id当订单号给用户看。外键的on_delete参数也值得认真选。普通业务数据建议用PROTECT或者CASCADE根据语义来但订单和电影、用户的关系我特意用了PROTECT——宁可让你删不了也不能一声delete下去把历史订单连带删光这种事故出了就是灾难。3. 售票主流程实现选座、锁定、下单、支付回调整链路3.1 为什么不能“下单后再锁座”这是整个系统最核心的一个设计决策。很多新手写售票流程是用户选座 - 创建订单 - 支付完成 - 更新座位。这套流程在演示时没问题但在真实并发下必出超卖——两个用户同时选同一个座位都下单了其中一个支付成功后才发现座位已经卖给别人。正确逻辑是把“锁座”放在下单前用户在界面上选中座位后先尝试锁定目标座位锁定成功才创建待支付订单支付成功才把座位状态从锁定改为已售超时未支付则释放座位。这样座位被锁后其他人就选不了超卖问题被扼杀在最前端。3.2 锁定座位在Django里的正确写法实现锁座不是简单的if判断要用数据库行锁配合事务。Django里核心是select_for_update()它会在事务内对查询出的行加锁其他人再查这些行就得等当前事务结束。下面这段是我实际在项目中验证过的核心逻辑from django.db import transaction def lock_seats_and_create_order(user, session_id, seat_ids): with transaction.atomic(): session Session.objects.select_for_update().get(pksession_id) session_seats list( SessionSeat.objects .select_for_update() .filter(session_idsession_id, seat_id__inseat_ids) .order_by(id) # 固定锁顺序避免死锁 ) for seat in session_seats: if seat.status ! SessionSeat.AVAILABLE: raise SeatLockedError(f座位 {seat.seat} 已被占用) order_no generate_order_no() order Order.objects.create( order_noorder_no, useruser, sessionsession, amountsession.price * len(session_seats), statusOrder.PENDING, ) for session_seat in session_seats: session_seat.status SessionSeat.LOCKED session_seat.save() Ticket.objects.create( orderorder, session_seatsession_seat, check_codegenerate_check_code(), ) return order几个细节必须提醒你。第一select_for_update()只有在事务内才生效所以一定要用transaction.atomic()包住这是我第一次踩坑的地方——在外面select_for_update()后去更新锁根本没起作用。第二锁定多条座位时order_by(id)是必要的它让所有并发请求按相同的顺序加锁避免两个请求各持一部分锁然后互相等待导致的死锁。第三这一整套逻辑在SQLite上有个大坑SQLite对select_for_update是不支持的它只是静默忽略也就是说本地开发一切正常一上生产换成PostgreSQL才触发真实锁行为。如果你用的是SQLite做开发和测试并发场景一定要放到生产数据库环境去验一遍。3.3 超时未支付订单怎么处理座位锁了但用户迟迟不付款座位就一直占着所以要有超时释放机制。最简单的做法是写一个Django management command扫描超时未支付订单回滚对应座位状态# app/management/commands/release_expired_orders.py from django.core.management.base import BaseCommand from django.utils import timezone from datetime import timedelta from django.db import transaction class Command(BaseCommand): help 释放超时未支付订单占用的座位 def handle(self, *args, **options): expire_before timezone.now() - timedelta(minutes15) expired_orders Order.objects.filter( statusOrder.PENDING, created_at__ltexpire_before, ) for order in expired_orders.iterator(): with transaction.atomic(): # 用select_for_update锁订单防止和支付回调竞争 locked_order Order.objects.select_for_update().get(pkorder.pk) if locked_order.status ! Order.PENDING: continue locked_order.status Order.CANCELLED locked_order.save() locked_order.tickets.select_related(session_seat) for ticket in locked_order.tickets.all(): ticket.session_seat.status SessionSeat.AVAILABLE ticket.session_seat.save()这个命令挂在系统cron里每5分钟跑一次就行。如果你用了Celery也可以用shared_task加beat_schedule定期执行如果项目没上Celery系统cron反而是最稳妥的选择。有一点特别容易忽略超时任务和用户支付回调可能同时发生——用户在最后一秒点了支付。所以处理超时时也要用select_for_update锁订单并再次判断状态否则会出现“订单被取消支付又成功”这种账单问题。3.4 支付回调幂等回调重复到达是常态模拟支付环节很多人直接在前端写死“支付成功”这会让整个订单链路失去真实感。正规做法是后端提供支付回调接口。所谓幂等就是同一个支付结果被通知两次、三次系统最终状态都一致不会把订单状态改出花来。def payment_callback(request): data json.loads(request.body) order_no data.get(order_no) with transaction.atomic(): order Order.objects.select_for_update().get(order_noorder_no) if order.status Order.PAID: return JsonResponse({code: 0, msg: duplicate}) if order.status Order.CANCELLED: # 理论上是异常流但要记录下来人工对账 send_alert_to_admin(order_no) return JsonResponse({code: 0, msg: cancelled but paid}) order.status Order.PAID order.paid_at timezone.now() order.save() order.tickets.select_related(session_seat) for ticket in order.tickets.all(): ticket.session_seat.status SessionSeat.SOLD ticket.session_seat.save() return JsonResponse({code: 0, msg: ok})判断order.status Order.PAID时直接返回就是幂等。如果不加这个判断回调来两次座位状态更新逻辑就会执行两次虽然结果可能一样但如果你在后面接上“给用户发短信”“生成发票”这类副作用操作重复执行就是事故。4. 权限体系与后台管理把Django Admin调教成运营工具4.1 自定义User模型越早做越好Django官方文档的一句话很多人没注意如果你打算自定义User模型应该在第一次迁移之前就做。一旦数据表建好再改User模型会非常痛苦。class User(AbstractUser): phone models.CharField(max_length20, blankTrue) class Meta: verbose_name 用户 verbose_name_plural 用户然后在settings.py里指明AUTH_USER_MODEL appname.User。为什么非要自定义因为你很可能在后续加角色、加手机号、加昵称、加头像。用默认User再挂一个Profile表虽说也能实现但查询和Admin集成就多绕一层。反正项目刚起步时改成本最低一次性自定义是最划算的选择。4.2 用Group做角色用Permission做权限Django的Group天然就是角色。我给这个项目至少准备三个组观众、前台员工、运营。管理员不需要放进组里is_staff和is_superuser字段已经区分了。具体到权限点除了Django自带的add/change/delete权限我建议你在模型Meta里自定义业务权限class Session(models.Model): # ... class Meta: permissions [ (can_publish_session, 可以发布场次), (can_check_ticket, 可以核销门票), ]然后用user.has_perm(app.can_check_ticket)判断一个前台能不能执行核销操作。视图层用permission_required装饰器拦住未授权访问前端模板里用{% if perms.app.can_check_ticket %}控制按钮显隐。后端校验永远比前端隐藏重要前端只是体验优化真正的安全边界在后端。在真实项目中前台员工现场售票应该只能修改订单状态不该有改电影信息的权限运营能排片和调价但不能修改用户数据——这些靠Group和Permission就能梳理得明明白白。4.3 Admin定制让运营愿意用而不是骂它默认的Admin其实已经够用但你要微调否则运营在一个满是英文的表单里手动填日期和价格一定会弃用。我在改造项目时主要定制了这几块admin.register(Movie) class MovieAdmin(admin.ModelAdmin): list_display (title, version, duration, release_date) list_filter (version, release_date) search_fields (title,) admin.register(Session) class SessionAdmin(admin.ModelAdmin): list_display (movie, hall, start_time, price, seat_booked_count) list_filter (start_time, hall) search_fields (movie__title,) autocomplete_fields (movie, hall) def seat_booked_count(self, obj): return obj.seat_status.exclude(statusSessionSeat.AVAILABLE).count() seat_booked_count.short_description 已占座位数 class TicketInline(admin.TabularInline): model Ticket extra 0 admin.register(Order) class OrderAdmin(admin.ModelAdmin): list_display (order_no, user, session, amount, status, created_at) list_filter (status, created_at) search_fields (order_no, user__username) readonly_fields (order_no, amount, created_at) inlines [TicketInline]运营最关心的是今天哪些场次快满了、哪些票还没卖出去、某个订单到底是什么状态。list_filter和list_display配好之后这些信息一眼就能看到。readonly_fields很重要——金额和订单号绝对不能让人在后台随手改要改只能走退款流程这是财务上的基本要求。5. 部署上线时最容易翻车的三个地方5.1 settings按环境拆分开发环境本地SQLite、DEBUGTrue生产环境PostgreSQL、DEBUGFalse这两套配置混在一起迟早出事。我的做法是拆成settings/base.py、settings/dev.py、settings/prod.py。base.py放公共项dev.py开DEBUGprod.py用环境变量读取数据库配置和SECRET_KEY。SECRET_KEY绝不能写死在代码里提交到仓库用环境变量或部署平台的密钥管理服务都行。# settings/prod.py import os DEBUG False ALLOWED_HOSTS os.environ[ALLOWED_HOSTS].split(,) SECRET_KEY os.environ[DJANGO_SECRET_KEY] DATABASES { default: { ENGINE: django.db.backends.postgresql, NAME: os.environ[DB_NAME], USER: os.environ[DB_USER], PASSWORD: os.environ[DB_PASSWORD], HOST: os.environ[DB_HOST], PORT: os.environ[DB_PORT], } }5.2 静态文件和媒体文件的处理海报上传这类ImageField字段涉及的media文件是另一个高频翻车点。开发时Django自己就能处理但生产环境千万别让Django处理静态文件。我建议Nginx直接代理/static/和/media/两个路径Django只负责动态请求。如果用单机部署不想单独配Nginx也可以用WhiteNoise这个库托管静态文件但media还是建议独立出来放OSS或云存储否则服务器存储和备份都会成问题。5.3 数据库迁移和并发测试别在本地草草了事最后一定要提醒如果你的开发环境一直是SQLite而线上是PostgreSQL那你至少要在上线前把整套流程在PostgreSQL上完整跑一遍业务测试。原因前面提过select_for_update在SQLite上不生效你在本地测不出并发问题此外PostgreSQL的字段约束、事务隔离级别、字符排序都和SQLite有差异。当初我帮人排查一个“本地测得好好的上线就漏单”的问题最后根因就是SQLite下并发锁形同虚设。部署时还有个小坑collectstatic是必须跑的漏了就会看到后台页面样式全部丢失。跑完之后检查一下STATIC_ROOT目录内容是否完整这个几秒钟的动作能省不少排查时间。我在实际做过这一整套之后最深的体会是这个题目看起来平淡其实是一个很好的“业务系统练兵场”。如果你能老老实实地把座位锁定、订单状态机、支付幂等、权限隔离这几块硬骨头都啃下来你收获的就不是一个课设而是一套能迁移到很多真实业务里的工程意识。下一次再遇到类似的项目你会发现难点都不在写代码而在想清楚每一步的状态和边界。

相关新闻

@reach/router 程序化导航完全指南:navigate() API 用法与源码原理剖析

@reach/router 程序化导航完全指南:navigate() API 用法与源码原理剖析

前端 【免费下载链接】router 项目地址&#xff1a; https://gitcode.com/gh_mirrors/rou/router 点击查看 免费下载 本文以 reach/router 的 navigate 函数为核心&#xff0c;系统讲解在 React 应用中如何通过代码触发路由跳转&#xff08;而非依赖用户点击 <Link>&…

2026/10/11 14:10:20 阅读更多 →
用架构决策记录(ADR)落地敏捷软件开发转型:architecture-decision-record 仓库示例全解析

用架构决策记录(ADR)落地敏捷软件开发转型:architecture-decision-record 仓库示例全解析

【免费下载链接】architecture-decision-record Architecture decision record (ADR) examples for software planning, IT leadership, and template documentation 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ar/architecture-decision-record 点击查看 免费下载 …

2026/10/11 14:10:20 阅读更多 →
N-Formyl-Met-Ala-Ser;17351-32-5

N-Formyl-Met-Ala-Ser;17351-32-5

基本性质中文名称&#xff1a;N - 甲酰基 - 甲硫氨酰 - 丙氨酰 - 丝氨酸简称&#xff1a;fMAS&#xff0c;N-Formyl-Met-Ala-Ser&#xff0c;趋化三肽单字母序列&#xff1a;fMAS&#xff08;fN-formyl 修饰于 N 端 Met&#xff09;三字母序列&#xff1a;N-Formyl-Met-Ala-Ser…

2026/10/11 14:10:20 阅读更多 →

最新新闻

现代机器人学课后答案:Grübler公式与自由度验算方法

现代机器人学课后答案:Grübler公式与自由度验算方法

简介&#xff1a;《现代机器人学》&#xff08;Modern Robotics: Mechanics, Planning, and Control&#xff09;官方配套课后习题答案&#xff0c;内容覆盖第2至第13章&#xff0c;涵盖自由度计算、运动学、动力学、路径规划与控制理论等核心主题。资源为单个PDF文件&#xff…

2026/10/11 15:04:53 阅读更多 →
贝叶斯网络入门:从DAG到后验概率推理与Python实践

贝叶斯网络入门:从DAG到后验概率推理与Python实践

简介&#xff1a;贝叶斯网络简介讲课稿是一份面向人工智能、机器学习初学者及课程教师的PPT教学资源&#xff0c;系统讲解贝叶斯网络如何用有向无环图表达变量依赖、以条件概率表量化不确定关系&#xff0c;并给出清晰的认知路径。内容从朱迪亚•佩尔1986年提出的背景展开&…

2026/10/11 15:04:53 阅读更多 →
Gatsby 嵌入 Twitter 推文与组件:gatsby-plugin-twitter 的配置、懒加载机制与版本演进解读

Gatsby 嵌入 Twitter 推文与组件:gatsby-plugin-twitter 的配置、懒加载机制与版本演进解读

前端静态站点Web框架 【免费下载链接】gatsby React-based framework with performance, scalability, and security built in. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ga/gatsby 点击查看 免费下载 本文围绕 Gatsby 官方插件 gatsby-plugin-twitter 展开&…

2026/10/11 15:04:53 阅读更多 →
RESTful服务中Hibernate实战:事务边界与懒加载优化

RESTful服务中Hibernate实战:事务边界与懒加载优化

1. RESTful服务要用ORM&#xff0c;到底图什么&#xff1f; 先说个我观察到的现象。很多做REST接口的同学&#xff0c;一听到Hibernate就皱眉&#xff0c;觉得它重、慢、不好控制&#xff0c;宁愿手写JDBC或者直接用MyBatis。但如果你搞的是以业务逻辑为核心、实体关系复杂、需…

2026/10/11 15:04:53 阅读更多 →
MATLAB聚类分析实战:从K-means到DBSCAN的完整指南

MATLAB聚类分析实战:从K-means到DBSCAN的完整指南

简介&#xff1a;面向数据挖掘、模式识别与市场细分等应用场景的聚类分析专题课件&#xff0c;围绕系统聚类、快速聚类及MATLAB实现展开&#xff0c;讲解Q型与R型聚类、样品间距离度量、谱系聚类步骤&#xff0c;并结合pdist、linkage、dendrogram、cophenet、cluster等函数给出…

2026/10/11 15:04:53 阅读更多 →
华为无线解决方案报告书:从设计到交付的WLAN避坑指南

华为无线解决方案报告书:从设计到交付的WLAN避坑指南

简介&#xff1a;这是一份华为无线解决方案报告书&#xff0c;以某集团无线覆盖项目为背景&#xff0c;系统讲解无线局域网从设计到落地的完整思路&#xff0c;适合网络工程师、方案架构师及高校通信相关专业学生参考。报告重点涵盖网络设计原则、无线信号质量分析、总体架构、…

2026/10/11 15:03:52 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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 阅读更多 →