Shanghai Library Seat Booking
by @jenslewie
上海图书馆东馆三楼座位预约。支持浏览器自动化登录获取认证信息,以及基于API的座位预约(指定座位或系统自动分配)。适用于需要自动化预约图书馆座位的场景。
clawhub install shlibrary-seat-booking📖 About This Skill
name: shlibrary-seat-booking description: 上海图书馆东馆三楼座位预约。支持浏览器自动化登录获取认证信息,以及基于API的座位预约(指定座位或系统自动分配)。适用于需要自动化预约图书馆座位的场景。 homepage: https://github.com/jenslewie/jenslewie-skills/tree/main/shlibrary-seat-booking metadata: openclaw: emoji: "📚" homepage: https://github.com/jenslewie/jenslewie-skills/tree/main/shlibrary-seat-booking requires: bins: - node - npm - npx install: - kind: brew formula: node bins: [node, npm, npx] label: Install Node.js - kind: node package: playwright bins: [playwright] label: Install Playwright
上海图书馆座位预约
通过上海图书馆预约接口,预约东馆三楼阅览座位。
功能特性
--area 南区 --seat-row 4排 --seat-no 2号 这样的直观输入--profile 切换不同账号前置条件
1. 拥有上海图书馆读者证(已开通借阅功能)
2. 已安装依赖(如果使用浏览器登录功能)
3. 如果使用预约模式,需要知道 日期和时段
4. 如果使用指定座位模式,还需要知道 区域、排号和座位号
5. 如果要切换到另一个账号,可以额外准备一个 profile 对应的认证文件
6. 不要求事先手动登录或手动保存认证文件;当使用 profile 文件时,book_seat.js 会在认证缺失或失效时自动拉起登录流程
适用方式
当前推荐统一使用子命令入口:
availability:查询某天全部时段都可用的座位list:查询当前账号已有预约cancel:取消指定预约book:预约座位当前脚本支持两类预约:
参数约定:
availability --date [日期] [--area 区域...]--date:必填,表示查询哪一天
- --area:可选,表示只扫描哪些区域;不传就查询全部区域
list [--profile 名称]cancel --reservation-id [预约ID]--reservation-id:必填,只负责指定要取消哪条预约
book --date [日期] [--period 时段] [--area 区域] [--seat-row 排号] [--seat-no 座位号]--date:整天自动分配
- --date + --period:单时段自动分配
- --date + --area + --seat-row + --seat-no:整天指定座位
- --date + --period + --area + --seat-row + --seat-no:单时段指定座位
- 参数值支持中文格式,例如:--area 南区 --seat-row 4排 --seat-no 2号常用命令速查
# 查询当前账号预约
node ./scripts/book_seat.js list查询指定账号预约
node ./scripts/book_seat.js list --profile user1查询 3 月 20 日在多个区域里整天都可用的座位
node ./scripts/book_seat.js availability --profile user1 --date 2026-03-20 --area 北区 西区 东区查询 3 月 20 日全部区域里整天都可用的座位
node ./scripts/book_seat.js availability --profile user1 --date 2026-03-20取消预约
node ./scripts/book_seat.js cancel --profile user1 --reservation-id 5187335按时段自动分配
node ./scripts/book_seat.js book --profile user1 --date 2026-03-24 --period 上午按时段指定座位
node ./scripts/book_seat.js book --profile user1 --date 2026-03-24 --period 下午 --area 南区 --seat-row 4 --seat-no 5整天自动分配
node ./scripts/book_seat.js book --profile user1 --date 2026-03-24整天指定座位
node ./scripts/book_seat.js book --profile user1 --date 2026-03-24 --area 南区 --seat-row 4 --seat-no 5
说明:
--profile 就使用默认账号--profile 会读取默认 profile 根目录下的 profiles/.json ~/.config/shlibrary-seat-booking--profile-dir 或 --auth-file 显式指定认证文件位置快速开始
方式1: 浏览器自动化登录(推荐)
Skill 提供了基于 Node.js + Playwright 的浏览器自动化脚本,可以自动完成登录并获取认证信息:
#### 安装依赖
# 在 skill 目录内安装 Playwright
cd /path/to/shlibrary-seat-booking
npm install playwright安装浏览器二进制
npx playwright install chromium
说明:
npm install playwright,这样 node ./scripts/*.js 才能稳定加载本地 playwright 依赖npx playwright install chromium 会联网下载 Chromium 浏览器二进制#### 运行登录脚本
# 默认账号登录
node ./scripts/login.js指定profile登录
node ./scripts/login.js --profile user1指定 profile 根目录
node ./scripts/login.js --profile user1 --profile-dir ~/.config/shlibrary-seat-booking直接指定认证文件
node ./scripts/login.js --auth-file ~/.config/shlibrary-seat-booking/profiles/user1.json
脚本会:
1. 打开浏览器并访问登录页面
2. 由你手动完成用户名、密码、验证码登录
3. 登录成功后自动检测并继续
4. 自动进入 seatyy / service/yuyue,优先直接调用 queryAuthInfo
5. 只有门户没有自动准备好时,才兜底尝试点击“预约”入口
6. 保存到对应的认证文件(默认 ~/.config/shlibrary-seat-booking/profiles/default.json)
#### 技术实现
seatyy -> service/yuyue -> queryAuthInfoaccessToken、sign、timestamp--profile 参数管理多个账号方式2: 手动获取认证信息
如果你更喜欢手动操作,或者想排查认证问题:
1. 先通过门户进入预约系统(通常会经过 service/seatyy 或 service/yuyue)
2. 使用读者证登录
3. 按 F12 打开浏览器开发者工具
4. 切换到 Network(网络)标签
5. 进入任意可触发预约系统接口的页面
6. 查看任意预约 API 请求的 Request Headers
7. 复制以下三个参数:
- accessToken
- sign
- timestamp
8. x-encode 不需要手动保存,脚本会在每次发请求前动态生成
2. 保存认证信息
如果使用浏览器自动化登录,认证信息会自动保存。
如果手动获取,将认证信息保存到文件:
mkdir -p ~/.config/shlibrary-seat-booking/profiles
cat > ~/.config/shlibrary-seat-booking/profiles/default.json << 'EOF'
{
"accessToken": "你的accessToken",
"sign": "你的sign",
"timestamp": "你的timestamp"
}
EOF
chmod 600 ~/.config/shlibrary-seat-booking/profiles/default.json
注意:
book_seat.js 会先探测登录态;如果认证来自 profile 文件且缺失或失效,会自动拉起 login.jscode 101 / 获取用户信息时出现异常,脚本也会按失效登录态处理如果你需要管理多个账号,也可以按 profile 名称保存多个文件:
~/.config/shlibrary-seat-booking/profiles/default.json
~/.config/shlibrary-seat-booking/profiles/user1.json
~/.config/shlibrary-seat-booking/profiles/user2.json
认证读取优先级是:
--auth-file:直接读取显式指定的单文件--profile-dir + --profile:读取 /profiles/.json --profile:读取 ~/.config/shlibrary-seat-booking/profiles/.json ~/.config/shlibrary-seat-booking/profiles/default.json认证写入规则是:
--auth-file:登录成功后写回该文件--profile-dir + --profile:写 /profiles/.json --profile:写 ~/.config/shlibrary-seat-booking/profiles/.json ~/.config/shlibrary-seat-booking/profiles/default.json补充说明:
book_seat.js 会先探测登录态;如果 profile 文件缺失或登录态失效,会自动拉起 login.js3. 预约座位
#### 预约座位
统一使用 book 子命令:
# 整天自动分配
node ./scripts/book_seat.js \
book --date 2026-03-24单时段自动分配
node ./scripts/book_seat.js \
book --date 2026-03-24 --period 上午整天指定座位
node ./scripts/book_seat.js \
book --date 2026-03-24 --area 南区 --seat-row 4 --seat-no 5单时段指定座位
node ./scripts/book_seat.js \
book --date 2026-03-24 --period 下午 --area 南区 --seat-row 4 --seat-no 5
脚本执行流程:
1. 按优先级读取认证文件 2. 如果认证缺失或失效,自动拉起登录流程 3. 根据参数组合判断是自动分配还是指定座位、整天还是单时段 4. 如果是指定座位,先查询目标时段的可用座位 5. 如果座位可用,再提交预约 6. 输出预约成功或失败信息
#### 系统自动分配
如果你只关心时间段,不关心具体座位,可以让系统自动分配:
# 预约3月22日上午,由系统自动分配座位
node ./scripts/book_seat.js \
book --date 2026-03-22 --period 上午
自动分配模式的流程:
1. 按优先级读取认证文件 2. 如果认证缺失或失效,自动拉起登录流程 3. 直接调用预约接口,请求系统分配可用座位 4. 输出预约成功或失败信息
也支持按时段标签自动分配:
node ./scripts/book_seat.js \
book --date 2026-03-22 --period 上午
如果要替另一个账号查预约:
node ./scripts/book_seat.js \
list --profile user1
4. 查询已有预约
如果你想先确认账号当前已经约了哪些时间段,可以直接查询:
node ./scripts/book_seat.js list
查询模式会:
1. 按优先级读取认证文件 2. 如果认证缺失或失效,自动拉起登录流程 3. 调用"我的预约"接口 4. 按日期分组打印当前账号的预约记录 5. 展示每条记录的时间段、座位、预约状态、预约 ID 和是否可取消
5. 查询整天公共可用座位
如果你想先筛出“某一天全部时段都可用”的位置,可以直接查询。这里日期是必填参数,区域通过 --area 可选传入:
node ./scripts/book_seat.js \
availability --profile user1 --date 2026-03-20 --area 北区 西区 东区
如果你不指定区域,脚本会自动扫描全部区域:
node ./scripts/book_seat.js \
availability --profile user1 --date 2026-03-20
这个模式会:
1. 读取对应 profile 的认证信息 2. 如果认证缺失或失效,自动拉起登录流程 3. 根据日期判断当天是 2 个时段还是 3 个时段 4. 扫描目标区域的所有排号和可用座位 5. 计算每个区域在当天全部时段的座位交集 6. 输出每个区域“所有时段都可用”的座位列表
说明:
--area 传一个或多个区域,例如 --area 北区 西区 东区2 / 3 / 4 / 56. 取消预约
如果你已经知道预约 ID,可以直接取消:
node ./scripts/book_seat.js cancel --reservation-id 5187335
取消模式会:
1. 按优先级读取认证文件 2. 如果认证缺失或失效,自动拉起登录流程 3. 调用取消预约接口 4. 输出成功或失败结果
更稳的使用顺序通常是:
1. 先执行 list
2. 找到目标记录的 预约ID
3. 再执行 cancel --reservation-id [预约ID]
时段映射规则
当前脚本按业务规则使用固定 mapping:
下午 -> 13:45:00-16:45:00
- 晚上 -> 17:00:00-20:30:00
- 上午 -> 不可用
上午 -> 09:15:00-12:45:00
- 下午 -> 13:00:00-16:30:00
- 晚上 -> 16:45:00-20:15:00如果图书馆后续调整了开放时段,这部分规则也需要同步更新。
整天预约顺序
当使用整天预约模式时,脚本会按这个顺序逐段尝试:
1. 下午
2. 晚上
3. 上午
这是一种 best-effort 策略:
1 秒,再继续下一段,尽量降低"请勿重复提交"这类频控问题自动重试策略
当前脚本对部分临时性失败做了短重试:
系统拥挤,请稍后再试 时3 次1.5 秒像这些明确的业务失败不会自动重试:
座位已约满该时间段有其他预约目标座位不可用区域 ID 对照
2: 东区3: 西区4: 北区5: 南区预约规则
参考资料
故障排除
认证失败
accessToken、sign、timestamp 三个字段是否都存在code 101 / 获取用户信息时出现异常,也按登录态失效处理座位不可用
系统自动分配失败
查询已有预约失败
code 101 / 获取用户信息时出现异常,通常也需要重新登录accessToken、sign、timestamp 后重试取消预约失败
预约ID 是否存在可取消: 是