基于 browser-harness 的 Flipkart 礼物选购自动化实战指南URL 过滤、登录弹窗处理与商品数据提取【免费下载链接】browser-harnessBrowser Harness | Self-healing harness that enables LLMs to complete any task.项目地址: https://gitcode.com/gh_mirrors/br/browser-harnessFlipkart 作为印度最大的电商平台之一其 Web 前端由 React 渲染、CSS 类名经过 Webpack 哈希混淆、且每个新会话都会弹出登录模态框对 LLM 驱动的浏览器自动化提出了独特的挑战。本文以 browser-harness 项目的领域技能文档 agent-workspace/domain-skills/flipkart/shopping.md 为主体结合 src/browser_harness/helpers.py 的 CDP 助手实现给出经过 2026-04-27/28 两天实战验证field-tested的完整方案。读完本文你将掌握用 URL 参数一步构建带价格/品牌/评分过滤的搜索页、用__NEXT_DATA__JSON 或 DOM 选择器提取商品卡片、绕开登录弹窗与图片缩放遮罩以及可靠的按邮编pincode配送查询流程。一、为什么选择「URL 优先」策略Flipkart 的搜索页是一个典型的 React 单页应用侧边栏筛选交互会触发 React 重渲染进而重置滚动位置、打断正在进行的点击流。因此实战结论的第一条铁律是把搜索关键词、价格区间、排序方式和品牌过滤全部编码进 URL而不是在页面加载后去点击侧边栏筛选器。这样既减少了交互步骤也规避了 SPA 状态重置的坑。搜索 URL 模板如下https://www.flipkart.com/search?q{query}marketplaceFLIPKARTp%5B%5Dfacets.price_range.from%3DMinp%5B%5Dfacets.price_range.to%3D{max_price}在 browser-harness 中通过goto_url()直接导航即可。goto_url()底层调用 CDPPage.navigate见 src/browser_harness/helpers.py是导航的核心助手。示例 1搜索 500 卢比以内的儿童礼物goto_url(https://www.flipkart.com/search? qgiftsforkidsunder10years marketplaceFLIPKART p%5B%5Dfacets.price_range.from%3DMin p%5B%5Dfacets.price_range.to%3D500)示例 2按价格升序排序的 200 卢比以内玩具goto_url(https://www.flipkart.com/search? qtoysforkids sortprice_asc p%5B%5Dfacets.price_range.from%3DMin p%5B%5Dfacets.price_range.to%3D200)注意一个关键编码细节p[]参数中的方括号必须做 URL 编码即p%5B%5Dfacets.price_range.to%3D500其中%3D是的编码。文档明确提醒p[]参数必须编码为p%5B%5Dfacets.price_range.to%3D500这种形式否则服务器无法正确解析过滤条件。URL 参数参考表参数类型示例说明qstringgiftsforkids搜索关键词pageint2分页从 1 开始sortstringprice_asc支持relevance、price_asc、price_desc、recency_desc、popularitymarketplacestringFLIPKART限制在 Flipkart 自营市场内p[]stringfacets.price_range.fromMin最低价过滤p[]stringfacets.price_range.to500最高价过滤p[]stringfacets.brandSamsung品牌过滤p[]stringfacets.rating4最低评分过滤如需类别导航还可以使用sid参数例如玩具类目为https://www.flipkart.com/toys/pr?sidtng可与价格 facet 组合实现带过滤的类目浏览。二、登录弹窗每个新会话都必须优先处理的第一障碍Flipkart 在每一个新的浏览器会话上都会弹出登录/注册模态框它会拦截所有页面交互直到被关闭。这是自动化失败的头号原因。文档给出的处理方式是在任何其他交互之前先用js()执行一次多重回退的关闭脚本。js()助手在 src/browser_harness/helpers.py 中实现它先按原样求值表达式如果 Chrome 报出非法顶层return则自动把表达式包进函数体重试因此下面这类同时包含赋值与return的 IIFE 写法可以安全执行。js(((){ var btn document.querySelector(button._2KpZ6l._2doB4z) || document.querySelector([class*close-btn]) || document.querySelector(button[aria-labelClose]); if (btn) { btn.click(); return closed; } var overlay document.querySelector(._2fS1Rz, ._3_UOR0); if (overlay) { overlay.click(); return overlay_dismissed; } document.dispatchEvent(new KeyboardEvent(keydown, {key:Escape, keyCode:27})); return escape_sent; })())这段脚本按三级回退执行优先点击已知类名的关闭按钮button._2KpZ6l._2doB4z是 Flipkart 弹窗关闭按钮的经典类名找不到按钮则点击遮罩层最后兜底派发 Escape 按键事件。如果 JS 关闭失败弹窗仍存在就改用坐标点击弹窗右上角的 ✕ 按钮。click_at_xy()通过 CDPInput.dispatchMouseEvent发送 mousePressed/mouseReleased 事件见 src/browser_harness/helpers.py坐标以视口像素计需先截图确认弹窗位置click_at_xy(720, 180) # 根据截图调整坐标结合 skills/browser-harness/SKILL.md 中的页面工作流建议截图前应优先用无障碍树Accessibility.getFullAXTree定位元素并计算盒模型中心点坐标只有 JS 关闭、坐标点击都失败时才截图人工判断。三、按邮编Pincode查询配送时效搜索页与详情页的差异搜索结果的每个商品下方虽然会显示预估配送天数但针对特定邮编的配送查询必须进入单个商品详情页才能完成。商品详情页的完整流程详情页的邮编输入框通常位于 Add to Cart 按钮附近流程分三步# Step 1: 找到并点击邮编输入框或 Change 链接 js(((){ var change [...document.querySelectorAll(span, a)].find( e e.textContent.includes(Change) e.closest([class*pincode], [class*delivery]) ); if (change) { change.click(); return clicked change; } var input document.querySelector(input[placeholder*pincode], input[placeholder*Pincode]); if (input) { input.focus(); input.select(); return focused input; } return not found; })()) # Step 2: 清空并输入新邮编 type_text(560077) press_key(Enter) # Step 3: 等待并读取配送预估 wait(3) delivery js(((){ var el document.querySelector([class*delivery], [class*shipping]); return el ? el.innerText.trim() : not found; })())这里type_text()走的是 CDPInput.insertText见 src/browser_harness/helpers.pypress_key(Enter)则会派发带物理code与虚拟键码的完整 keyDown/keyUp 事件序列src/browser_harness/helpers.py能正确触发页面的事件监听器。已知坑Gotcha部分商品页修改邮编会触发登录要求。如果输入邮编后出现登录提示说明该商品的配送查询必须登录才能完成——此时不要强行登录直接采用搜索结果页展示的默认配送预估即可。四、商品评估工作流为礼物选购构建结构化评估进入商品详情页后可用一段js()一次性抽取价格、评分、评分人数、亮点、配送、库存与卖家信息返回 JSON 字符串便于后续解析# After navigating to a product page: evaluation js(((){ var price document.querySelector(div._30jeq3, [class*selling-price])?.innerText?.trim(); var rating document.querySelector(div._3LWZlK)?.innerText?.trim(); var ratingCount document.querySelector(span._2_R_DZ)?.innerText?.trim(); var highlights Array.from(document.querySelectorAll(li._21Ahn-)) .map(e e.innerText.trim()).filter(Boolean); var delivery document.querySelector([class*delivery])?.innerText?.trim(); var inStock !document.querySelector([class*out-of-stock], [class*sold-out]); var seller document.querySelector([id*seller] a, div._3enH42)?.innerText?.trim(); return JSON.stringify({price, rating, ratingCount, highlights, delivery, inStock, seller}); })())礼物适配性检查清单价格Price——是否在预算内注意解析₹前缀与印度式逗号分组格式评分Rating——优先选 4.0 分以上且评论数 ≥ 50 的商品配送Delivery——用邮编查询配送预估确认在要求天数内可送达库存Availability——确认页面可见 In Stock / Add to Cart 按钮耐用性Reusability——阅读亮点/描述判断材质与耐久度是否适合作礼物五、搜索结果页的侧边栏过滤补充方案虽然推荐 URL 优先但某些场景需要在页面加载后再微调价格或评分过滤按价格过滤侧边栏输入框# Flipkart 的价格过滤位于左侧边栏 # 查找价格区间输入框 js(((){ var inputs document.querySelectorAll(input[class*price], input[name*price]); return inputs.length price inputs found; })())按评分过滤侧边栏点击js(((){ var stars [...document.querySelectorAll(div, label)].find( e e.textContent.includes(4★) e.closest([class*filter]) ); if (stars) { stars.click(); return clicked 4-star filter; } return not found; })())按配送速度过滤Flipkart 并非所有页面都暴露配送天数侧边栏过滤当可用时寻找 Delivery in X days 复选框。六、搜索结果数据提取的两种策略策略 1__NEXT_DATA__JSON首选Flipkart 使用 Next.js 风格的 SSR页面内嵌__NEXT_DATA__脚本标签其中包含结构化的商品数据。这种提取方式对 CSS 类名变更免疫是最稳定的方案。从源码结构看__NEXT_DATA__是一棵深层的 JSON 树需要通过递归遍历定位商品数组import json nd_raw js(document.getElementById(__NEXT_DATA__)?.textContent) if nd_raw: nd json.loads(nd_raw) # Walk the JSON tree to find product arrays def find_products(obj, depth0): if depth 8: return None if isinstance(obj, list) and len(obj) 3: if isinstance(obj[0], dict) and any(k in obj[0] for k in [title,name,price,productId]): return obj if isinstance(obj, dict): for v in obj.values(): result find_products(v, depth 1) if result: return result return None items find_products(nd)递归深度限制为 8 层避免在超大 JSON 树上做无界遍历当某层列表首元素包含title/name/price/productId等键时判定其为商品数组。策略 2DOM 选择器回退方案当__NEXT_DATA__不可用例如某些轻量页面或改版后时回退到 DOM 选择器。核心思路是以a[href*/p/]作为稳定锚点商品详情链接格式长期不变再向上回溯到商品卡片容器results js(((){ var links Array.from(document.querySelectorAll(a[href*/p/])); var seen new Set(); return links.map(a { var href a.getAttribute(href); if (seen.has(href)) return null; seen.add(href); var card a.closest([data-id]) || a.closest(div[class]); if (!card) return null; return { title: card.querySelector(div._4rR01T, a.IRpwTa, a.s1Q9rs)?.innerText?.trim() || a.getAttribute(title) || card.querySelector(img)?.getAttribute(alt), price: card.querySelector(div._30jeq3)?.innerText?.trim(), rating: card.querySelector(div._3LWZlK)?.innerText?.trim(), url: https://www.flipkart.com href, }; }).filter(Boolean); })())用Set去重同一商品的多个链接title字段按卡片类名 → 链接 title 属性 → 图片 alt三级回退最大限度容忍选择器失效。七、实战经验教训Field-Tested Lessons以下 10 条来自 2026-04-27/28 两天的真实对抗测试是本文最值得沉淀的部分URL 优先策略——把搜索词、价格区间、排序、品牌过滤直接编码进 URL尽量避免操作侧边栏过滤侧边栏交互会触发 React 重渲染并重置滚动位置。登录弹窗是必须处理的——每个新浏览器会话都会命中登录模态框必须在任何其他交互之前关闭它JS 关闭失败就用坐标点击关闭按钮。邮编配送查询有局限——修改商品页配送邮编可能要求登录搜索结果页展示的默认配送预估无需登录即可使用。图片缩放遮罩陷阱——商品页的图片缩放遮罩层会吞掉本应落到其他元素的点击。如果交互突然失效先按Escape关闭所有遮罩再重试。印度价格格式——价格使用₹前缀与印度式分组₹1,23,456 123,456 INR。解析方式.replace(/[₹,]/g, )。wait_for_load()之后仍需等待 3 秒——商品卡片由 React 异步渲染readyStatecomplete触发时卡片尚未渲染完成。首次加载 Flipkart 使用new_tab()——首次访问时goto_url()可能因当前标签页拒绝导航而静默失败。这与 skills/browser-harness/SKILL.md 及 interaction-skills/tabs.md 的指导一致任务首次导航用new_tab(url)而非goto_url(url)daemon 会跨 CLI 调用保持已附加的标签页。从源码看new_tab()src/browser_harness/helpers.py会先复用空白标签页否则后台创建新标签页再附加避免与 attach 竞态。Flipkart 屏蔽数据中心 IP——来自云服务商如 Playwright Service的远程/无头浏览器会得到ERR_CONNECTION_TIMED_OUT。Flipkart 只对住宅 IP本地 Chrome开放云环境自动化可考虑改用 FirstCry 等替代站点购买儿童用品。类目浏览页——用sid参数做类目导航https://www.flipkart.com/toys/pr?sidtng直达玩具类目可与价格 facet 组合过滤。混淆类名频繁变动——Flipkart 使用 Webpack 哈希类名_4rR01T、_30jeq3等。选择器失效时以a[href*/p/]为稳定锚点向上找卡片容器优先使用对类名变更免疫的__NEXT_DATA__提取。八、把方案接入 browser-harness 运行环境上述所有代码片段都运行在 browser-harness 的browser-harnessCLI 环境中——所有助手goto_url、js、click_at_xy、type_text、press_key、scroll、page_info、wait等在脚本执行前已被自动导入见 src/browser_harness/run.pydaemon 也会在exec前自动启动。典型运行方式browser-harness PY new_tab(https://www.flipkart.com/search?qtoysforkidsmarketplaceFLIPKART) wait(3) print(page_info()) PY几个值得注意的运行约束开启领域技能domain skills 默认关闭需设置BH_DOMAIN_SKILLS1开启后goto_url()会返回对应站点如 flipkart的技能文件清单tests/unit/test_helpers.py 中有对应测试验证这一行为。建议在开始 Flipkart 任务前先读取本目录下的技能文档。住宅 IP 前提第 8 条经验决定这套方案面向本地 Chrome住宅 IP环境。若必须用云浏览器优先考虑替代站点。安装与连接一次性安装可参考 install.md连接失败先运行browser-harness --doctor诊断。代理助手扩展如需把某些 Flipkart 专用原语沉淀下来可以写入 agent-workspace/agent_helpers.py——该文件会被helpers模块在导入时自动加载src/browser_harness/helpers.py注意以公开命名非_开头定义即可被导出。九、写在最后一套可复用的对抗式电商自动化范式Flipkart 的这套经验不只是某个站点的零散技巧它沉淀出一套对 LLM 电商自动化普遍有效的范式把状态放进 URL用参数化导航替代脆弱的 UI 交互优先消灭全站性模态框在业务交互之前做一次性的弹窗清理结构化数据优先走内嵌 JSONDOM 选择器只做回退对异步渲染建立显式等待预算readyState完成不代表 React 渲染完成对反爬环境提前做可行性评估IP 信誉比选择器技巧更决定成败。这套范式可以平移到 FirstCry、Amazon 印度站等同类平台——只需要替换各自的 URL 参数模板与弹窗选择器。当你下次接到在某个印度电商平台选礼物的任务时先按 URL 参数构造搜索、再清弹窗、再提数据就能把成功率从碰运气提升到可预期。【免费下载链接】browser-harnessBrowser Harness | Self-healing harness that enables LLMs to complete any task.项目地址: https://gitcode.com/gh_mirrors/br/browser-harness创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
