news 2026/10/8 16:09:50

OpenClaw Skill实战:跨境电商数据抓取从写死脚本到组装技能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenClaw Skill实战:跨境电商数据抓取从写死脚本到组装技能

做跨境电商,最烦的不是选品,而是每天要花两三个小时在不同网站上手动复制价格、库存和评论数。早些年我用现成采集器,功能倒是全,可平台一改版就抓瞎;后来自己写爬虫脚本,能用是能用,但每换一个站点、每加一个字段,都要从头改代码。直到我接触了 OpenClaw 和它的 Skill 机制,才把这件事从“写死脚本”变成了“组装技能”。这篇文章就围绕 OpenClaw Skill 在跨境电商数据抓取里的完整用法展开,从 Skill 的核心概念、配置细节,到实际写一个能跑通的抓取技能,再到我踩过的各种坑,一次讲清楚。适合手里有具体抓取需求、又不想每次求人写脚本的运营和开发朋友参考。

有必要先解释一下 OpenClaw 是什么。你可以把它理解成一个本地的智能体框架,大模型在里面当“调度员”,负责理解你说的话;而 Skill 是这个框架下的专业技能包,相当于挂在调度员手下的工具。要抓数据,就装一个抓取类 Skill;要写商品文案,就挂一个文案类 Skill。它们互相独立,又能随意组合。这和传统爬虫最大的区别在于:你不需要每次把需求翻译成代码,而是用大白话告诉它“把这几页的商品数据抓下来”,它自己会去调用对应的 Skill 执行。

下面我把这个过程拆开讲,包括我为什么这样选型、Skill 里到底该写什么、完整实操流程是什么样,以及那些报错信息背后到底在说什么。

1. 为什么偏要用 OpenClaw 做数据抓取

1.1 传统爬虫脚本的痛点

我自己早期写爬虫,流程基本是:确定目标网站、分析页面结构、用 requests 和 BeautifulSoup 写解析、然后放在 crontab 里定时跑。听着挺顺,但实际用起来问题不少。

首先是维护成本高。跨境电商平台平均一两周就要改一次页面,类名、CSS 路径说变就变。你今天写好的解析逻辑,明天可能就返回一堆空值。每改一次,就要打开浏览器的开发者工具重新定位元素,再把正则和选择器改一遍,纯粹是重复劳动。

其次,业务方不会考虑技术实现。运营同事的需求往往是“看看这个商品在东南亚三个站点的价格差异”“顺便把评价里的关键词频次也统计一下”。这些需求听起来简单,但实际上每一句话背后都是一个独立任务,每个任务都有自己的反爬策略和数据格式。如果用一个大脚本去全部实现,代码会越来越臃肿,最后只有你自己敢碰,别人根本改不动。

还有一个问题是缺少容错机制。Requests 超时了怎么办?IP 被临时限制了怎么办?页面结构变了导致解析出来的数据是空的怎么办?传统脚本遇到这些问题,最多打印几行错误日志,然后等着你发现。等你在第二天早上看到数据表里一堆 NaN,才发现昨晚的采集全挂了,那些窗口期已经过去了。

1.2 Skill 机制到底解决了什么问题

OpenClaw 的 Skill 机制,本质上把“一次性脚本”变成了“可复用能力”。

我举个例子。你在 OpenClaw 里写一个 Skill,命名为“商品信息采集”,描述写成“抓取目标店铺的商品标题、价格、销量和上架天数,返回结构化数据”。这个 Skill 内部可以是一个 Python 脚本,也可以是一串提示词加工具调用。以后你只要在对话里输入“采集一下 XXX 店铺的最新商品信息”,OpenClaw 就会自动匹配到这个 Skill,并让大模型根据描述生成调用参数去执行。

这样做有个非常实际的好处:写一次,多处复用,而且不需要重新学习每个网站的结构。你只要把 Skill 的脚本设计成“传入 URL,输出结构”的通用接口,那么换平台的时候只需要改 Skill 内部实现,调用方完全不用动。

其次,Skill 之间可以互相调用。比如我抓完评论数据后,会再写一个“评论摘要”Skill,把抓回来的评论丢给它,让它生成一段卖点总结。这两个 Skill 解耦,一个管采集,一个管分析,坏了一个不影响另一个。这种组合能力是传统一个大爬虫脚本很难做到的,因为脚本之间一旦耦合,改一个地方就会牵连别的地方。

还有一个容易被忽略的点:OpenClaw 是多端部署的。窗口期数据这种需求,往往需要机器长时在线。OpenClaw 可以跑在 Windows 上,也可以在 Ubuntu 服务器上常驻,甚至手机 Termux 里也能跑起来,配合 Ollama 部署本地模型。采集任务挂在任何一端都行,不挑环境。这一点对跨境电商这种“需要盯不同时区数据”的场景非常重要,你不需要为临时采集需求单独租服务器,身边的电脑、旧手机都能变成采集节点。

2. Skill 的构成与关键参数

2.1 一个 Skill 的标准目录结构

OpenClaw 的 Skill 一般是一个独立目录,里面有说明文件、脚本文件和辅助资源。每个框架对目录要求不一样,但通用的结构大致如下:

skills/ ecommerce-scraper/ SKILL.md scripts/ scrape_products.py requirements.txt assets/ user_agent.txt sites.yaml

其中SKILL.md是这个技能的名片,也是大模型理解这个技能的唯一入口。OpenClaw 会优先读取这个文件来决定“什么时候该调用这个 Skill”。如果名片写得含糊,模型就可能在你想抓数据的时候跑去调用别的 Skill,或者干脆告诉你“我不知道怎么做”。

scripts文件夹放真正的可执行代码,这里就是你的爬虫脚本;assets放一些辅助配置,比如请求头模板、站点列表、代理配置(合规代理,用于正常访问公开网络资源)。

我习惯在SKILL.md里写清楚三样东西:触发场景、输入参数、输出格式。触发场景告诉模型“用户在什么诉求下应该选择我”;输入参数告诉模型“调用时该传哪些字段”;输出格式告诉模型“脚本结果怎么展示给用户”。把这三点写清楚,Skill 的识别准确率会高非常多。

2.2 配置项解读:触发词、模型、编码

不少读者在热搜里看到“skill 编码 193”“skill 编码 247”,以为这是什么神秘规则。其实没那么玄。Skill 编码就是技能库里的唯一标识或版本号,方便框架在调度时快速定位对应技能。193、247 只是不同资料里出现的示例编号,相当于你给每个技能贴的 ID,自己在配置里维护好递增就行,不必过度解读。

真正的核心配置项是这几个:

配置项作用我的建议
name技能名称,注册到框架的唯一标识用简短英文,如ecommerce_scraper
descriptionSkill 的名片,决定模型能不能正确调用写清楚“何时用、怎么用、输出什么”
trigger_words触发词,帮助模型更快匹配覆盖常见说法,如“抓取”“采集”“爬虫”“监控价格”
model指定该 Skill 使用哪个模型抓取类用工具调用能力强的模型
timeout脚本超时时间抓取多页数据时给足时间,比如 300 秒
version技能版本每次修改都对版本号+1,方便回溯

trigger_words的作用很容易被新手忽略。OpenClaw 的默认行为是“先用语义匹配,再结合描述判断”。如果你在描述里写了“抓取”,但用户说的是“帮我看一下这个链接里有没有货”,语义匹配可能偏掉。把“有没有货”“库存”“价格多少”这些口语化表达一并写进触发词,实际使用时会顺滑很多。

2.3 抓取类 Skill 必须处理的四个细节

Skill 机制本身只是调度层,真正决定采集成败的还是脚本里的细节。我在写抓取类 Skill 时,无论目标站点长什么样,都会先处理这四件事:

第一是请求头伪装。直接发一个默认 Python-requests 请求,很多平台的边缘节点会直接拒绝。至少要带上 User-Agent、Accept、Accept-Language 和 Referer。UA 建议用一个主流浏览器真实版本,不要用爬虫框架的默认 UA。Referer 也很有用,很多站点对图片或列表页做了防盗链校验,带上前一页的地址会更自然。

第二是会话与登录态。公开数据一般不用登录,但有些数据需要登录后才能看到。我自己常用的办法是先用浏览器手动登录一次,把 Cookie 复制出来,存到assets/cookies.json里,脚本启动时用requests.Session()加载。注意 Cookie 会过期,Skill 里要预留“采集失败并提示重新登录”的分支,不要一直拿过期 Cookie 重试。

第三是限速与随机延时。跨境电商平台对采集频率非常敏感,一个 IP 每秒发几十个请求,不封你封谁。我在脚本里会用一个随机延时函数,每抓一页随机睡 1.5 到 3.5 秒。这样做不是为了慢,而是为了把请求节奏模拟成真人浏览的波动。另外一个原则是并发数宁可低不要高,抓数据不是抢火车票,慢一点没关系,稳定最重要。

第四是页面解析策略。优先找页面里内嵌的 JSON 数据,很多现代站点会把商品数据直接放在<script id="__NEXT_DATA__">或window.__INITIAL_STATE__里,这种结构化数据比解析 HTML 稳定得多。只要页面是用 Vue 或 React 写的,大概率都有这种全局数据对象,用正则或者 json 解析直接拿,比 CSS 选择器靠谱十倍。

3. 实操:从零搭建一个可落地的采集 Skill

3.1 环境部署要点与算力选择

实操开始前,先把环境准备好。OpenClaw 的部署并不复杂,但要看你把它跑在哪里。

Windows 用户直接下官方安装包,装完在命令行里执行openclaw init初始化配置目录,然后openclaw run启动交互终端即可。Ubuntu 服务器上更简单,用系统包管理器装好 Python 3.10 以上版本和 Docker,再从仓库拉镜像跑,几分钟就能起来。手机端可以用 Termux,在 Termux 里装完依赖后同样能跑,虽然性能一般,但抓取低频率数据完全够用。

至于热搜里反复出现的“openclaw 只能用接入 API 的方式使用算力吗”,这个说法不太准确。OpenClaw 本身只是个框架,算力由模型决定。你可以接入各家的云端模型 API,也可以接本地模型(比如通过 Ollama 启动 Qwen、Llama 系列)。两者差别主要在于:本地模型数据不出内网,隐私安全,但语义理解能力和工具调用能力通常不如云端模型。像抓取这种对“精准调用 Skill 参数”要求高的场景,如果本地显存只有 8G,我建议还是用 API 方式;如果是跑在 24G 显存的机器上,本地模型完全能胜任。

我个人推荐的第一步流程是:先在 Windows 或 Ubuntu 上把 OpenClaw 跑起来,日志级别调到 debug,随便内置一个示例 Skill 试一下,确认链路通了,再开始写自己的抓取技能。这个“先跑通最小链路”的习惯,能帮你节省后面大量排查时间。

3.2 定义采集需求与 Skill 骨架

我们拿一个具体场景举例:你想采集某跨境平台上“蓝牙耳机”这个关键词下前 5 页的商品数据,内容包含标题、价格、评论数、店铺名,并且去重后存到 SQLite 里。为了演示方便,下面代码里的目标地址用https://example-store.test代替,实际使用时替换成你有权采集的目标即可。

第一步,在skills目录下新建一个ecommerce_scraper文件夹,然后写SKILL.md:

# 商品信息采集 ## 一句话描述 抓取目标店铺或搜索结果页的商品标题、价格、评论数、店铺名,输出结构化记录。 ## 触发场景 - 用户提到“采集商品”“抓取价格”“看看某关键词下的商品数据” - 用户给一个店铺地址或搜索页地址,要求整理商品信息 ## 输入参数 - url: 目标列表页地址 - max_pages: 最多抓取多少页,默认 3 - save_path: SQLite 数据库保存路径,默认 ./products.db ## 输出格式 - 返回成功条数和保存路径 - 若失败,返回失败原因及最后成功页数 ## 使用说明 1. 脚本按 max_pages 循环翻页 2. 每页随机延迟 1.5~3.5 秒 3. 数据写入 SQLite,按商品标题去重

这个文件的核心价值不是给人看的,而是给模型看的。模型读到描述后会知道:用户在什么需求下该调它、参数怎么传、结果怎么汇报。所以写的时候要尽量贴近用户的真实说法,而不是写一堆技术术语。

3.3 抓取脚本代码拆解

接下来写scripts/scrape_products.py。这里我不给你一个耍花活的大长脚本,而是一个结构分明、适合二次修改的版本:

import argparse import json import random import sqlite3 import time import requests from bs4 import BeautifulSoup HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", } def create_table(db_path): conn = sqlite3.connect(db_path) conn.execute(""" CREATE TABLE IF NOT EXISTS products ( title TEXT PRIMARY KEY, price TEXT, reviews TEXT, shop TEXT, url TEXT, crawled_at TEXT ) """) return conn def parse_page(html): soup = BeautifulSoup(html, "html.parser") items = [] for card in soup.select("[data-product-card]"): title = card.select_one("[data-title]") price = card.select_one("[data-price]") reviews = card.select_one("[data-reviews]") shop = card.select_one("[data-shop]") if title and price: items.append({ "title": title.get_text(" ", strip=True), "price": price.get_text(strip=True) if price else "", "reviews": reviews.get_text(strip=True) if reviews else "0", "shop": shop.get_text(strip=True) if shop else "", "url": "", }) return items def save_to_db(conn, items): cur = conn.cursor() for it in items: cur.execute(""" INSERT OR REPLACE INTO products (title, price, reviews, shop, url, crawled_at) VALUES (?, ?, ?, ?, ?, datetime('now')) """, (it["title"], it["price"], it["reviews"], it["shop"], it["url"])) conn.commit() def main(): parser = argparse.ArgumentParser() parser.add_argument("--url", required=True) parser.add_argument("--max-pages", type=int, default=3) parser.add_argument("--save-path", default="./products.db") args = parser.parse_args() conn = create_table(args.save_path) total = 0 for page in range(1, args.max_pages + 1): url = f"{args.url}?page={page}" try: resp = requests.get(url, headers=HEADERS, timeout=20) resp.raise_for_status() except Exception as e: print(f"page {page} failed: {e}") break items = parse_page(resp.text) save_to_db(conn, items) total += len(items) print(f"page {page} saved {len(items)} items, total {total}") time.sleep(random.uniform(1.5, 3.5)) conn.close() print(f"DONE total={total}") if __name__ == "__main__": main()

这段代码有几个设计上的考虑。用INSERT OR REPLACE而不是普通INSERT,是为了天然按标题去重,重新采集时不会攒一堆重复数据。选择器全部写成>page 1 saved 18 items, total 18 page 2 saved 17 items, total 35 page 3 saved 20 items, total 55 ... DONE total=90

如果脚本报错,OpenClaw 会把 stderr 里的异常信息原样反馈到对话里。这时候不要急着改代码,先看报错类型:如果是 HTTP 403,说明被平台拦截,检查请求头和频率;如果是 JSON 解析失败,说明页面结构变了,需要重新定位数据位置;如果是连接超时,则考虑加超时重试。

运行成功后,我建议你手动打开 SQLite 文件检查一遍数据质量。用命令行sqlite3 mydb.db "select count(*) from products;"就能看到总数。数据抓取这件事,脚本跑完不是结束,先人工抽查几行再确认“可用”,这个习惯能避免很多脏数据带来的后续麻烦。

4. 常见问题与排查技巧实录

4.1 Skill 不触发或触发错误

新手遇到最多的问题是:明明已经写好了 Skill,对话里说“抓取一下”,OpenClaw 却回答说“我帮你搜索了一下”之类的话,完全没有调用技能。

这种情况大概率是SKILL.md的description和trigger_words写得太窄。模型在判断是否调用工具时,本质是语义匹配。你的描述里只写“采集商品”,可用户说的是“看一下有没有货”,这两个语义并不直接相通,模型就不会匹配。解决办法是把触发词扩展成口语化表达的集合,越贴近真实用户说法越好。另一个常见原因是模型本身不支持工具调用。OpenClaw 依赖模型的 function calling 能力,如果你用的是纯文本模型,它就永远无法触发任何工具。换一个支持工具调用的模型,问题立刻消失。

最后还有一种情况:Skill 目录结构不对。OpenClaw 一般会扫描特定目录,你必须确保 Skill 文件夹放在配置指定的skills_dir下,并且SKILL.md的文件名拼写完全正确。有的版本要求用skill.json而不是 Markdown,这个以你使用的版本官方文档为准,但一旦搞混,框架会直接跳过该技能并且没有任何提示。

4.2 请求被拒、IP 受限、出现验证码

采集请求返回 403 或验证码,基本可以断定请求被识别成机器行为了。常见的三个原因:请求频率过高、请求头特征太明显、行为模式过于规律。

我自己的处理策略是分等级排查。先给每个请求加随机延时,观察是否缓解;再把 User-Agent、Accept 等头信息补全,模仿真实浏览器完整请求链;如果还是被限制,就降低总采集量级,比如一台机器单日只采 2000 条。很多人追求“采集速度”,但我一直觉得跨境数据采集这个场景,稳定比速度重要得多。数据源一旦封了你,损失的时间远超慢速采集节省的时间。

遇到验证码,我的建议是不要做任何自动破解。合规的做法是:检测到验证码特征后,停止当前任务并通知人工处理,人工过一下验证码后在会话里续跑。这一条写在SKILL.md里作为强制规则,能帮你避开大量法律与合规风险。

4.3 页面结构变化导致解析失败

这是跨境电商抓取里最普遍、最避不开的问题。平台前端每隔一段时间就会改版,原来的>

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

企业AI应用落地:基于Spring Cloud与JDK 21的微服务底座实战

1. 从一个真实困境说起&#xff1a;为什么“能跑起来的 AI”和“能上线的 AI”是两回事过去一年多&#xff0c;我参与过好几个企业内部的 AI 应用落地项目&#xff0c;从最早的“拿个开源模型跑个 Demo”&#xff0c;到后来要给几百人的业务团队交付一个真正能用的智能问答、智…

作者头像 李华
网站建设 2026/10/8 16:07:50

Space Bunny登顶OpenRouter:匿名模型接入与实战指南

一个名字听起来像玩具的“Space Bunny”&#xff0c;最近直接把大模型调用量排行榜干翻天了。我刷 OpenRouter 的实时榜单时&#xff0c;它稳稳坐在第一位&#xff0c;把 Claude Opus 5、GPT-5 这些熟脸全都压下去了。很多人在群里问&#xff1a;这到底是什么模型&#xff1f;怎…

作者头像 李华
网站建设 2026/10/8 16:07:49

程序员AI协作实操指南:从提示工程到责任闭环

1. 这不是“被取代”的焦虑&#xff0c;而是“协作界面”重构的实操现场 “AI下半场&#xff0c;程序员如何与AI协作”——这句话最近在技术社区刷屏&#xff0c;但很多人一看到就下意识点开又关掉&#xff0c;觉得又是那种泛泛而谈的“未来已来”式鸡汤。我去年底开始系统性地…

作者头像 李华
网站建设 2026/10/8 16:07:04

最长递增子序列LIS:动态规划与贪心二分解法全解析

力扣热题100里排在第87位的这道最长递增子序列&#xff0c;原题号其实是300. Longest Increasing Subsequence。我刷到这一题的时候有点意外——大名鼎鼎的LIS&#xff0c;居然在热题100里藏得这么靠后。不过位置靠后不代表它简单&#xff0c;这几乎是动态规划入门绕不开的关卡…

作者头像 李华
网站建设 2026/10/8 16:06:56

GDN与线性注意力GPU并行实现:scan与chunk优化

最近被问得最多的一个问题&#xff1a;GDN&#xff08;Gated DeltaNet&#xff09;这类Linear Attention&#xff0c;在GPU上到底怎么并行实现&#xff1f;老实说&#xff0c;这个问题比“怎么调FlashAttention”要复杂一个档次。标准Attention的并行套路已经被FlashAttention讲…

作者头像 李华
网站建设 2026/10/8 16:06:56

零参考撰写博士介绍:从信息考证到成稿的方法论

接到一个任务&#xff1a;让我写一篇"Federico Municchi 博士介绍"的文章。但我手里只有这个标题&#xff0c;没有他的简历&#xff0c;没有他的论文列表&#xff0c;也没有任何可复制的官方介绍段落。面对这种情况&#xff0c;最省事的做法是去搜索引擎搜一圈&#…

作者头像 李华