ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

k-skill 技能实战:基于 `__NEXT_DATA__` 服务器渲染数据的 오늘의집 今日特价商品查询(ohou-today-deal)

2026/9/18 22:23:31 拓冰建站 浏览量
k-skill 技能实战:基于 `__NEXT_DATA__` 服务器渲染数据的 오늘의집 今日特价商品查询(ohou-today-deal) k-skill 技能实战基于__NEXT_DATA__服务器渲染数据的 오늘의집 今日特价商品查询ohou-today-deal【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill导读ohou-today-deal是 k-skill 技能集中面向韩国家居电商 오늘의집Ohouse的一款只读特价商品查询技能它不依赖任何登录态或 API Key仅通过 Python 标准库抓取公开的今日特价오늘의딜页面并从 Next.js 服务器渲染的__NEXT_DATA__初始数据中提取商品、价格与折扣信息。本文将完整解析该技能的指令文档与源码实现涵盖数据来源、CLI 参数、排序过滤逻辑、离线验证方式以及全部失败模式读者读完后既能直接用npx命令查询特价商品也能理解其诚实 UA、不做绕过、标准库解析的设计取舍。一、技能定位这个技能做什么、什么时候用按照 packages/k-skill-cli/skills/ohou-today-deal/instruction.md 的定义该技能从 오늘의집 公开的今日特价页面https://ohou.se/commerces/today_deals中读取服务器渲染初始数据__NEXT_DATA__从而完成오늘의딜 / 스페셜딜Today Deal / Special Deal商品列表查询整理折扣率、原价、售价以及叠加优惠券/支付优惠后的最低价best price展示品牌、评论数、平均评分、是否免运费、商品链接支持关键字、最低折扣率、免运费等组合过滤。适用场景典型对话示例文档原文오늘의집 오늘의딜 뭐 있어?오늘의집 今日特价有什么오늘의집에서 할인율 높은 특가 상품 3개 보여줘帮我挑折扣率最高的 3 件特价商品오늘의집 무료배송 특가만 골라줘只挑免运费的特价오늘의집에서 러그 특가 찾아줘帮我找地毯特价技能边界同样明确刻意不做以下事情登录、购物车、购买、支付自动化个性化推荐与用户专属优惠券的最终确认具有法律证明力的价格认定价格仅为查询时点参考以及任何形式的拦截绕过或 CAPTCHA 绕过——文档明确写道用标准库urllib一次调用搞不定就按失败模式处理。从 ohou-today-deal/skill.json 可以看到该技能声明了browser与action:commerce两种 profilefrontmatter 标记category: retail、locale: ko-KR、phase: v1并在描述中注明在 돌쇠Dolshoi运行时中还会通过官方页面继续后续动作。二、公开数据面为什么是__NEXT_DATA__而不是页面选择器技能依赖的公开数据面只有一处MethodURL用途GEThttps://ohou.se/commerces/today_deals今日特价公开 HTML服务器渲染关于 URL 有一个值得注意的细节文档原文页面本身通过 canonical/OG 标签暴露的是https://store.ohou.se/today_deals但浏览器可直接访问的公开 URL 是ohou.se/commerces/today_deals技能以这个 URL 为抓取目标。解析策略的核心结论是优先服务器渲染初始 JSON而不是依赖页面 DOM 选择器。具体来说技能只读取响应 HTML 中 Next.js__NEXT_DATA__内嵌脚本里的 React QuerydehydratedState并且只认可两个 queryKeytoday-deal-feedspecial-today-deal-feed两者均取其state.data.todayDealFeed.slots列表。其他页面模块导航navigation、横幅banner等中即使存在type: DEAL的相似节点也一律忽略。这一白名单过滤设计可以在 scripts/test_ohou_today_deal.py 的测试用例中得到印证test_navigation_deal_like_node_is_excluded断言navigation查询中的type: DEAL广告横幅节点id9999999不会被收录test_non_deal_slot_types_are_excluded断言type: GOODS的槽位同样被排除。诚实 User-Agent不做绕过的自我声明技能向服务器发送的请求头为User-Agent: k-skill-ohou-today-deal/1.0 (https://github.com/NomaDamas/k-skill) Accept: text/html,application/json文档特别解释了这一设计的背景ohou.se 前端的 Akamai bot manager 会拦截匿名或短 User-Agent例如python-urllib、单独的Mozilla/5.0但包含机器人名 contact URL的 well-formed UA 可以正常通过。因此技能不是去伪装浏览器而是通过真实、规范的自我声明来合法访问——这既是工程策略也与其不绕过任何访问控制的法律边界一致详见 ohou-today-deal/references/DISCLAIMER.md其中引用了韩国大法院关于公开信息收集的判例并强调不得用于批量爬取与数据库构建。三、前置条件与运行方式前置条件极简文档原文python3无需任何登录、无需 API Key。运行入口是 k-skill CLI若本机未安装 Node.js 18 可先通过npx自动拉取npx -y nomadamas/k-skill0 exec ohou-today-deal scripts/ohou_today_deal.py -- list --limit 10npx -y nomadamas/k-skill0会自动下载并运行 k-skill CLIexec子命令负责在技能目录内执行辅助脚本。此外 CLI 还提供两条技能配套命令见 ohou-today-deal/SKILL.md# 获取技能最新指令CLI 会根据运行环境自动裁剪输出 npx -y nomadamas/k-skill0 instruct ohou-today-deal # 列出技能随附的所有辅助文件 npx -y nomadamas/k-skill0 files ohou-today-deal技能本体指令、脚本、skill.json、法律声明同时存在于仓库根目录的 ohou-today-deal/ 与 CLI 打包目录 packages/k-skill-cli/skills/ohou-today-deal/两者保持同步。四、CLI 参数无输入可跑全部可选技能无输入即可执行所有参数都是可选项完整清单如下结合 ohou-today-deal/scripts/ohou_today_deal.py 中parse_args的参数校验实现参数说明取值/默认值--url抓取地址默认https://ohou.se/commerces/today_deals--html-file离线 HTML/JSON fixture 路径测试/离线验证用传入后不再发起网络请求--query商品名或品牌关键字大小写不敏感casefold后子串匹配--min-discount最低折扣率0~100 的整数越界直接报错退出--free-delivery仅返回免运费商品布尔开关store_true--include-sold-out是否包含已售罄商品布尔开关默认排除售罄商品--sort排序标准default/discount/price/review/annual-sales默认discount--limit返回结果条数正整数默认 10参数校验值得单独说明_discount_rate()会把--min-discount强制限制在0 x 100_positive_int()会拒绝0、负数和非整数输入不符合时以argparse.ArgumentTypeError终止。测试类OhouArgvalidatorTest对边界值0/50/100与非法值-1/101/abc都做了覆盖。五、四个实战工作流1. 查询今日特价商品默认按折扣率排序npx -y nomadamas/k-skill0 exec ohou-today-deal scripts/ohou_today_deal.py -- list --limit 10对应的响应示例指令文档原文节选首条商品{ source: { name: ohou-today-deal, url: https://ohou.se/commerces/today_deals, fetched_at: 2026-05-18T01:44:1600:00, surface: __NEXT_DATA__ today-deal-feed special-today-deal-feed }, filters: {query: null, min_discount: null, free_delivery: false, sort: discount, limit: 10}, count: 10, total_count: 72, filtered_count: 72, items: [ { id: 823405, title: 삼익가구 BEST상품 총집합, brand: 삼익가구, url: https://ohou.se/productions/823405/selling, original_price: 449000, selling_price: 132000, discount_rate: 70, best_price: 118800, best_discount_rate: 73, best_discount_description: 쿠폰 할인가, review_count: 53818, review_average: 4.7, free_delivery: false, sold_out: false } ] }2. 按折扣率排序discount技能对折扣率的定义有一个优先级规则源码sort_deals与_normalize_deal共同实现优先使用bestDiscountPrice.discountRate叠加优惠券/支付优惠后的折扣率不存在时才回退到商品基础discountRate。排序时以该折扣率为第一关键字、评论数为第二关键字降序。npx -y nomadamas/k-skill0 exec ohou-today-deal scripts/ohou_today_deal.py -- list \ --sort discount \ --limit 5其余排序选项price按最低价升序使用best_price缺失时回退selling_price、review评论数多优先同评论数看平均分、annual-sales年累计销量降序。3. 关键字 · 最低折扣率 · 免运费组合过滤以下命令只返回商品名或品牌包含러그地毯、折扣率 ≥ 30%、且免运费的商品取前 5 条npx -y nomadamas/k-skill0 exec ohou-today-deal scripts/ohou_today_deal.py -- list \ --query 러그 \ --min-discount 30 \ --free-delivery \ --limit 5filter_deals()在单次循环里依次检查四个条件源码可查默认剔除售罄商品关键字子串匹配casefold后同时检查标题与品牌best_discount_rate or discount_rate达到阈值免运费开关。测试用例test_filter_and_sort_deals用一个含 2 件商品的样本验证了该组合过滤结果只命中地毯商品。4. 离线 fixture 验证不带网络即可用本地保存的 HTML/JSON 文件跑通完整解析链路适合测试、离线演示与故障排查npx -y nomadamas/k-skill0 exec ohou-today-deal scripts/ohou_today_deal.py -- list \ --html-file ./today-deals.html \ --limit 3底层实现里extract_next_data()做了双格式兼容若文档以{开头则直接按 JSON 解析否则用正则script[^]*id__NEXT_DATA__[^]*(.*?)/script提取内嵌脚本并html.unescape后再解析。测试用例test_extract_next_data_accepts_html_script和test_cli_prints_json_from_html_file分别验证了 HTML 解析与--html-file端到端 JSON 输出。六、输出格式与字段语义默认输出为indent2的美化 JSONensure_asciiFalse韩文不会被转义。文档建议在管道/脚本场景中用jq等工具后处理。顶层字段语义如下字段说明source.fetched_at查询时点UTC ISO 8601count实际返回的商品数total_count当日全部今日特价商品数filtered_count应用过滤条件后的商品数items[].best_price叠加优惠券/支付优惠后的最低价无则 nullitems[].best_discount_rate叠加优惠后的折扣率无则 nullitems[].free_delivery是否免运费items[].sold_out是否售罄此外从源码build_payload()还可以看到两点文档未展开的细节一是source中除了 UTC 的fetched_at还额外输出fetched_at_kst韩国标准时间%Y-%m-%d %H:%M:%S KST方便本地语境阅读二是items[]中每条商品还会带上image_url、scrap_count收藏数、annual_sales年销量以及活动起止时间start_at/end_at等扩展字段来自OhouDealdataclass见 ohou-today-deal/scripts/ohou_today_deal.py#L38-L61。商品 URL 的拼接规则在源码中固定为https://ohou.se/productions/{deal_id}/selling即技能只负责带用户到商品页不替代用户在页面上完成任何购买动作。七、源码级解析链路从 HTML 到结构化商品把ohou_today_deal.py的数据管线拆开核心流程为fetch_html()构造User-AgentAccept请求头urlopen读取响应按Content-Type声明的 charset 解码缺省 utf-8超时 20 秒。请求头中不加 Cookie、不加任何浏览器指纹。extract_next_data()如上所述支持 JSON 直读与__NEXT_DATA__脚本提取两种形态。_iter_today_deal_feeds()在props.pageProps.dehydratedState.queries数组中只挑出 queryKey 精确匹配TODAY_DEAL_FEED_KEYS ((today-deal-feed,), (special-today-deal-feed,))的条目并产出每个条目的state.data.todayDealFeed.slots。这是只信白名单、不信树里任何 DEAL 节点的关键隔离层。_looks_like_deal_node()判定槽位节点必须是type DEAL且deal.id、deal.name均非空从结构上排除GOODS等其他槽位类型。_normalize_deal()从嵌套 JSON 的price、bestDiscountPrice、brand、reviewStatistic、scrapInfo、badgeProperties、salesStats中逐一取出字段并做类型安全转换_to_int/_to_float对空值与非法值统一返回None缺字段一律安全降级为 null/默认值。extract_deals()先走上面的显式 feed 分支并按deal.id去重若 payload 中没有可识别的 React Query feed例如简化的测试 fixture才回退到基于显式栈的 DFS 遍历_walk()全树收集 DEAL 节点——_walk特意用迭代栈而非递归以规避sys.getrecursionlimit()限制。回退分支只影响 fixture/旧结构线上页面永远走显式分支。filter_deals()→sort_deals()→ 截断[:limit]完成过滤、排序与条数限制后由build_payload()组装成带source/filters/ 计数的最终 JSON。需要强调整个脚本没有引入任何第三方依赖仅用argparse、urllib.request、re、json、html、dataclasses等标准库模块from __future__ import annotations保证类型注解在旧版 Python 下也可解析。这正是指令文档新增零依赖、只用 Python 标准库承诺的实现。八、测试验证测试套件如何守住解析契约技能附带的测试位于仓库根目录 scripts/test_ohou_today_deal.py共覆盖四个维度字段规范化OhouTodayDealTest用模拟的公开结构样本验证extract_deals()正确产出 id、标题、品牌、原价/售价/最低价/最佳折扣率、免运费与商品链接同时验证--html-file端到端 CLI 输出。React Query 结构契约OhouReactQueryShapeTest构造与线上一致的dehydratedState结构断言today-deal-feedspecial-today-deal-feed两个 queryKey 的 DEAL 槽位被收录id111、222而navigation中的广告类 DEAL 节点与GOODS槽位被排除——这是前文白名单隔离的直接证据。参数校验OhouArgvalidatorTest验证--limit拒绝 0/负数、--min-discount拒绝越界值并接受边界值。测试加载方式测试通过importlib.util.spec_from_file_location直接加载技能脚本模块无需安装任何包即可运行与技能零依赖的理念保持一致。九、失败模式页面结构变化时的自查清单指令文档为每一种常见异常都给出了明确信号与处理策略这是该技能长期可维护的关键异常信号处理__NEXT_DATA__未发现ValueError: Could not find __NEXT_DATA__ in Today Deal HTML오늘의집 改版了 Next.js SSR 结构或改为纯客户端渲染需要更新解析器today-deal-feedqueryKey 未发现extract_deals()返回空列表total_count: 0React Query 键名变更需要把TODAY_DEAL_FEED_KEYS常量更新为新键名HTTP 403请求被 Akamai bot manager 拦截大概率是 UA 丢失了机器人名 contact URL特征不做绕过打印错误后退出其他 HTTP 4xx/5xx临时故障不做绕过打印错误后退出空响应total_count: 0今日特价尚未更新或页面结构变化引导用户直接在浏览器确认价格/优惠变动best_price仅代表查询时点不同用户的优惠券/支付方式可能导致实际支付价不同需在回答中显式说明字段缺失bestDiscountPrice、badgeProperties.isFreeDelivery、scrapInfo等字段在部分商品上不存在统一按 null 处理不中断解析十、回答规范、完成标准与使用边界指令文档对如何把结果呈现给用户也有严格要求先展示前 3~5 条结果整理输出商品名、品牌、折后价、原价、折扣率、评分/评论数、免运费与否、商品链接明确声明价格、折扣、售罄状态、优惠券/支付优惠均以查询时点为准、可能变动不自动化购买/购物车/支付只提供商品链接禁止지금 사라快去买这类诱导性表述购买行为由用户自己在页面上完成。Done when完成标准三条件返回商品候选的 JSON 或摘要列表折扣率/价格依据与查询时点被分开说明全程未尝试登录、购买、支付与个性化功能。结合 ohou-today-deal/SKILL.md 的硬性规则该技能的使用边界还可总结为只读优先服务器渲染初始 JSON 而非屏幕选择器零新依赖绝不绕过访问控制。配套的 ohou-today-deal/references/TRADEMARK-LEGAL-STATEMENT.md 与 DISCLAIMER 进一步限定公开商品信息采集仅限个人、非组织化查询用途禁止批量爬取、数据库构建与转载原始图片/详情且文档本身不构成法律意见。结语ohou-today-deal是一个小而克制的范例用 370 行左右的标准库脚本 一个公开页面就实现了可离线验证、可组合过滤、可排序、带完整失败模式与法律边界的特价查询能力。它的核心方法论——优先读取服务器渲染初始 JSON、用 queryKey 白名单隔离有效数据、以诚实 UA 而非伪装绕过换取访问——不仅适用于 오늘의집也为其他页面即 API场景的技能开发提供了可复用的思路。想要实际体验直接运行本文第 5 节中的任意命令即可想要深入实现可继续阅读 ohou-today-deal/scripts/ohou_today_deal.py 与 scripts/test_ohou_today_deal.py 两个文件。【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考