news 2026/9/20 13:29:55

court-auction-notice-search 完整解析:3 层防护下的法院拍卖公告结构化查询客户端

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
court-auction-notice-search 完整解析:3 层防护下的法院拍卖公告结构化查询客户端

court-auction-notice-search 完整解析:3 层防护下的法院拍卖公告结构化查询客户端

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

大法院运营的拍卖门户 courtauction.go.kr 没有任何公开 Open API,IP 级机器人拦截又凶得很。k-skill 仓库里的court-auction-notice-search直接复用该站内部的 WebSquare JSON XHR 接口,把 매각공고(不动产拍卖公告)与案件数据转换成 Agent 可直接消费的 JSON,设计哲学一句话:慢即是稳

一个没有 API 的政府站,逼出了什么方案

你面对的目标是这样的:想查"某天某个法院有哪些拍卖",官网上只有搜索表单;表单背后是 WebSquare 前端框架发出的 JSON POST 请求,没有文档、没有 SDK、没有公开端点列表。换句话说,唯一的数据获取方式就是精确模仿浏览器里那个搜索按钮的行为——包括请求体结构、Referer、会话 Cookie。

第二个约束更硬:站点按 IP 做激进拦截,实测大约 30 秒内 16 次请求就会触发约 1 小时的封禁。一个常规的"并发抓全量"脚本,在这里活不过半分钟。

第三个约束是合规:拍卖数据用于参考,真正的投标必须由人在法院完成。这个包因此被明确定位为 read-only 客户端——它只读,不写,不提交,不填表。

这三条约束(无 API、强反爬、合规红线)直接决定了后面所有设计决策的走向。

架构解析:为什么主通道是裸 HTTP,浏览器只是备胎 🧭

整体数据流只有一条主线:你的调用 → index.js 的参数归一化 → http.js 的CourtAuctionHttpClient.postJson→ 站点内部 5 个 endpoint → normalize.js 的字段翻译 → 结构化 JSON 返回。

决策一:默认传输用直接 HTTP,不碰浏览器。公告列表、公告详情、案件直查三条主路径在真实浏览器里验证过,裸 HTTP 完全走得通。省掉浏览器意味着省掉登录态依赖、省掉启动开销、省掉被封后需要"人肉接管"的复杂局面。落到代码上,http.jsENDPOINT_PATHS集中了全部 5 个 POST 路径,每个请求都带X-Requested-With: XMLHttpRequest、韩语Accept-Language和按 endpoint 分配的Referer,发送前先对对应入口页做一次 warmup GET 来拿到会话 Cookie。

决策二:浏览器只给自由检索兜底。Workflow C(物件自由条件检索)走的 endpoint 被站点 WAF 盯得更紧,裸 HTTP 有时会收到 WAF 型 400。playwright.js 的CourtAuctionPlaywrightClient就为此而生,优先级是:用户已打开的 Runtime 浏览器(Aside → BrowserOS → Chrome CDP)→ 全部够不到才chromium.launch本地启动。注意顺序的意义:优先复用用户自己的浏览器,是因为那台浏览器的指纹与会话更接近"真人",被拦概率最低。

决策三:2 秒最小间隔 + 1 秒 jitter。对照"30 秒 16 次就封"的实测红线,默认minDelayMs: 2000jitterMs: 1000意味着相邻两次调用间隔 2000~2999ms 不等,随机增量把固定节奏的"机器味"打散。

决策四:每会话 10 次调用预算。ensureBudget在每次postJson前检查计数,超了直接抛BUDGET_EXCEEDED。这不是 bug 是保险丝:它保证即使你的循环写错了,一个客户端也烧不出 16 次/30 秒的量。

按日期查拍卖公告:公告列表与案件展开

回答"今天/明天哪里有不动产拍卖"这类问题,用searchSaleNotices

参数必填取值说明
dateYYYY-MM/YYYYMM/YYYY-MM-DD/YYYYMMDD站点的搜索按钮只按月发请求,给特定日期时先查整月再在本地按日过滤(见 index.js 的toNoticeSearchDate
courtCodeB000210(首尔中央地方法院)空字符串 = 全部法院
bidTypedate/period/기일입찰/기간입찰/000331/000332别名、中文名、代码都收;空 = 两种都查

返回items[]里每条公告都带caseNumber无关字段——重点是有judgeDeptCode(即jdbnCd,法院返回的加密令牌)、saleDatesaleTimescorrectionCountcancellationCount,以及原样透传的raw

const { searchSaleNotices, getSaleNoticeDetail } = require("court-auction-notice-search"); async function run() { const ann = await searchSaleNotices({ date: "2026-04-27", courtCode: "B000210", bidType: "date" }); // 逐条展开公告,取出案件号/用途/地址/评估价/最低价 const view = await getSaleNoticeDetail(ann.items[0]); // 错误处理:catch BLOCKED 后停止 for (const row of view.items) { console.log(row.caseNumber, row.address, row.appraisedPrice, row.minimumSalePrice); } }

展开公告时最容易踩的点是:getSaleNoticeDetail需要jdbnCd,而这个令牌只存在于列表响应的raw,外部无法凭空构造。所以最简单的姿势就是把列表返回的items[i]整个对象原样塞回去,构造逻辑会自动从raw里抽取cortOfcCddspslDxdyYmdjdbnCdbidDvsCd

案件号直查:三步拿到完整进展

回答"2024타경100001 这个案子走到哪一步了",用getCaseByCaseNumber,只需两个入参:

参数必填说明
courtCode^B\d{6}$强校验,格式不对直接本地报错
caseNumber推荐2024타경1000012024-1000012024_100001会被normalizeCaseNumber自动补成标准形态

found: true时返回一份很完整的档案:caseInfo(案件名、受理日、请求金额、裁判部、进行状态)、items[](拍卖目的物地址与分配请求终期)、schedule[](每个拍卖日的最低价/评估价/结果)、claimDeadlinerelatedCasesappealsstakeholders。这些子表在 normalize.js 的normalizeCaseDetailResponse里逐一展开,足以支撑"上次拍卖流拍了吗""上诉结果如何"这类追问。found: false / status: 204时别当成故障——案件不存在或非公开,应当让用户核对案件号和法院是否匹配。

自由条件筛物件:区域、用途、价格、流拍次数

回答"江南区 5 亿以下、流拍 1 次以上的公寓",用searchProperties

参数必填约束
region: {sido, sigungu, dong}sido 可传代码或韩语名;시군구/읍면동 无静态表,直接传 raw 代码(如11680
usage: {large, medium, small}5 位代码(건물=20000)或大分类韩语名
priceRange/appraisedPriceRange韩元{min, max},允许小数
saleDate{from, to}
flbdCount{min, max}仅整数
area{min, max}
pageSize只能10/20/50/100(默认 10),其他值上游会回 400,本地直接拒绝

一个隐含行为:传了region就走 지번주소 检索(请求体里cortStDvs:"2"),不传则切公告模式(cortStDvs:"1"),切换逻辑在 index.js 的buildPropertySearchBody里。返回items[]的 raw 列做了英文键翻译,常用的几组:saNocaseNumbergamevalAmt/minmaePriceappraisedPrice/minimumSalePriceyuchalCntflbdCountboCd/jiwonNmcourtCode/courtName

代码表方面有两个值得学的取舍。其一,getUsageCodes()只固化了 4 个大分类和部分中/小分类,getRegionCodes()只固化 19 个 시도——시군구级联 XHR 不稳定,索性不做静态表,未知值一律 fail-open 透传,让错误在源头可见而不是被静默改写成"看起来对"的代码。其二,codetables/index.js 的resolveUsageCode有同名保护:"아파트"在大/中/小多层都存在,若按名字跨层匹配就会把错误的代码写进请求体,所以指定了层级却匹配不上时,宁可原样透传。

使用前必须交代的合规红线 🚨

这一节的内容要在每次使用场景中告诉用户,没有例外。

诚实声明清单(原文照发,不用"建议您"):

  1. 数据是法원경매정보站公开信息的原样搬运,投标前必须回法院原始公告复核
  2. 该站对自动化极度敏感,快速连续查询会封 IP 约 1 小时,封后同一 IP 需等约 1 小时;
  3. 价格、拍卖日期、场所均以公告时点为准,可能因correctionCount/cancellationCount反映的正正·撤回·延期而变动;
  4. 本客户端 read-only,绝不自动投标。

⚠️封禁(data.ipcheck === false)不要自动重试。站点把重试流量视为持续攻击,只会延长封禁;正确动作是立即停止、把封禁事实与等待指引交给用户,等约 1 小时或换网络。

⚠️pageSize只有 4 个合法值。15之类"看起来合理"的值,本地校验直接抛错;这是被上游 400 打疼后加上的前置拦截。

⚠️连到用户自己的浏览器时只清 page/context/tab。Runtime 浏览器属于用户,fallback 结束只断开 automation client,绝不关闭 BrowserOS/Aside/Chrome 的 profile;只有本地 launch 的浏览器才整体关闭。

fail-open 与 fail-closed 的分界也在这里:未知代码、未知法院代码是 fail-open(透传,让上游裁决);而PLAYWRIGHT_UNAVAILABLE(fallback 模块缺失)和错误的 provider 名是 fail-closed(立即抛错,绝不静默降级成一个更脆弱的通道)。

限流参数怎么调:默认值与更保守的客户端 🔧

默认节流四件套:调用间 ≥2000ms + 0~1000ms 随机增量、每会话 10 次预算、单次超时 15s、封禁即停。两个调节面:

  • CLI 全局标志--min-delay-ms 3000拉大间隔、--max-calls 5收紧预算、--timeout-ms改超时(见 cli.js)。
  • 注入自造客户端CourtAuctionHttpClientminDelayMs/jitterMs/maxCallsPerSession/timeoutMs全部可 override,传进任意主函数的client参数即可。
const { CourtAuctionHttpClient, searchSaleNotices } = require("court-auction-notice-search"); const cautious = new CourtAuctionHttpClient({ minDelayMs: 3000, jitterMs: 2000, maxCallsPerSession: 5, timeoutMs: 30_000 }); const first = await searchSaleNotices({ date: "2026-05", client: cautious });

预算用尽后,开一个新客户端实例即重置计数;要更高 burst,间隔拉到 3~5 秒并换客户端。自由检索在裸 HTTP 遇到 WAF 型 400 时会自动走浏览器 fallback;想彻底关掉就传fallback: false,而BLOCKED默认中止,只有显式fallbackOnBlocked: true才会再试一次。

实战演练:从安装到第一条数据 🛠️

# 安装(npm 包名与 CLI 同名;也可 clone 仓库后在 packages/ 下构建) npm install court-auction-notice-search # 1) 先拿法院代码表,确认目标法院的 B000xxx court-auction-notice-search codes courts --pretty | head -40 # 2) 查某月某法院的公告列表 court-auction-notice-search notices --date 2026-04 --court-code B000210 --bid-type date --pretty # 3) 案件号直查 court-auction-notice-search case --court-code B000210 --case-number "2024타경100001" --pretty

search子命令还支持--region <시도[:시군구[:읍면동]]>--usage <대[:중[:소]]>--appraised-min/max--flbd-min/max--page-size 10|20|50|100等,完整用法见court-auction-notice-search -h或 README.md。Node.js 侧的最小集成就是前面 Query A 的示例:主调用两行,catch里判断error.code === "BLOCKED"分支单独提示即可。

排错速查:5 类错误各给一个 30 秒动作 🩺

错误码触发条件30 秒自助动作
BLOCKED响应data.ipcheck === false停止一切重试,告知用户约 1 小时后或换 IP 再试
BUDGET_EXCEEDED会话调用超预算新建一个CourtAuctionHttpClient实例,或调大maxCallsPerSession
UPSTREAM_ERROR站点返回通用错误最常见是会话过期或jdbnCd失效,丢弃旧客户端从 warmup 重来;看error.upstreamMessage定位
NETWORK_ERROR超时/连接失败核对timeoutMs与网络;原始异常在error.cause
PLAYWRIGHT_UNAVAILABLE想用浏览器 fallback 但模块没装npm i rebrowser-playwright(或playwright-core)后重试

收尾:这套保守客户端范式能迁移到哪

三句话总结设计哲学:传输上保守(默认裸 HTTP,浏览器只在被 WAF 打脸时出场)、输出上结构化(raw 列全量翻译为语义键并保留raw兜底)、边界上清晰(read-only、封禁即停、预算保险丝、同名代码保护)。

延伸阅读按这个顺序走:instruction.md 是技能视角的完整工作流 → README.md 的 Endpoints used 表记录了每个请求体的 canonical 键 → index.js 看参数归一化与 fallback 判定 → http.js 看节流与错误构造 → 最后翻 test/fixtures/ 的响应夹具,其中canonical-search-body.json由 capture-pgj151-submit.cjs 从真实浏览器提交捕获,是理解请求结构的最佳样本。

凡是"无公开 API + 强反爬 + 合规敏感"的政务/金融站点查询,"慢即是稳 + 分层 fallback + 预算即停"这套组合都可以原样搬过去。

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

数模C题实战:多源融合定位与任务优化算法解析

简介&#xff1a;面向2025年数学建模竞赛C题参赛者的完整代码与思路资源包&#xff0c;覆盖问题分析、假设设定、模型建立、求解与验证、结果评估等完整流程。资源以代码和结果为核心&#xff0c;不含论文形式内容&#xff0c;适合已有一定建模基础、希望快速参照实现或复现结果…

作者头像 李华
网站建设 2026/9/20 13:29:42

ESM蛋白质语言模型原理与实战:从Transformer到结构预测

1. 这不是又一篇“Transformer万能论”——ESM系列到底在解决什么真问题&#xff1f;你点开这篇&#xff0c;大概率是因为看到“Transformer”和“蛋白质结构预测”这两个词被强行拉到一起&#xff0c;心里犯嘀咕&#xff1a;一个搞NLP的模型&#xff0c;凭什么去碰生物界最硬的…

作者头像 李华
网站建设 2026/9/20 13:26:04

基于Python的兵棋推演游戏源码解析与二次开发指南

简介&#xff1a;这是一份基于Python实现的兵棋推演游戏源码&#xff0c;面向对人工智能与战略模拟感兴趣的开发者&#xff0c;可用于学习智能体通信、指令处理与可视化推演流程。资源共35个文件&#xff0c;包括33个Python脚本、1个txt及1个markdown说明&#xff0c;压缩包仅1…

作者头像 李华