Finance Data Analysis
AI驱动的财务分析与可视化工具,支持KPI追踪与自动化报告生成。
通过自然语言指令自动抓取网页数据并导出为CSV,支持复杂页面结构处理。
openclaw skills install @science-prof-robot/auto-scraping-to-csv命令、参数、文件名以原文为准
使用基于文本的 DOM 操作抓取任意网页,并将结构化数据导出为 CSV。该代理能够处理复杂的页面特性——无限滚动、分页、弹窗、懒加载等,并在数据不明确时提出澄清问题。无需外部大语言模型。
传统抓取需要你手动检查 HTML,编写 CSS 选择器,处理边缘情况,并在网站变更时调试。本技能颠覆这一流程:
你说你想要什么,代理负责实现方式。
你: "抓取产品目录"
代理: "我看到共有 50 个产品分布在 5 页中,且支持无限滚动。
还发现 '价格'、'促销价' 和 '会员价' 三个字段。
应该提取哪个价格?"
你: "促销价"
代理: [自动滚动、分页,提取 50 行] → products.csv代理将执行以下操作:
Claude (主机模型)
↕ HTTP
桥接服务器 (Node.js + Playwright)
↕ page.evaluate()
浏览器 (Chromium) ← 注入页面代理 [5]<a >Widget Pro Laptop /></a>
[12]<div >$1,299.99 /></div>
[18]<div >4.5 星 (128 条评价) /></div>npm install -D playwright
npx playwright install chromium# 从本技能文件夹复制到你的 agents 目录
cp .claude/skills/auto-scraping-to-csv/page-agent-bridge.mjs .claude/agents/node .claude/agents/page-agent-bridge.mjs默认端口:9876
curl http://localhost:9876/health/scrape-to-csv https://example.com/products
"提取所有产品,包括名称、价格、评分和评价数量"代理会获取 DOM 状态,可能提出如下问题:
代理: "当前页面发现 24 个产品。该网站支持无限滚动,
滚动后会加载更多内容。
你需要多少条数据?(输入 'all' 表示全部)"
你: "50"
代理: "我看到三个价格字段:
- 原价:$1,299
- 促销价:$999
- 会员价:$899
应该提取哪一个?"
你: "促销价"
代理: "部分产品缺货,价格显示为 'N/A'。
你希望如何处理?
A) 保留这些行,值为 'N/A'
B) 跳过这些行
C) 在单独列中标记为 '缺货'"
你: "C"代理将自动完成:
代理: "已提取 50 个产品。以下是预览:
| 名称 | 价格 | 评分 | 评价数 | 库存状态 |
|------|------|------|--------|----------|
| Widget Pro | $999 | 4.5 | 128 | 有货 |
| Gadget Mini | $499 | 4.2 | 89 | 有货 |
| ... | ... | ... | ... | ... |
是否保存为 'products.csv'?(yes/no/修改列名)"
你: "yes"代理: "已保存至 ./products.csv — 共 50 行,5 列"你: "抓取此动态 feed 中的所有帖子"
代理: "该页面每滚动一次加载 10 条帖子。
我已滚动 3 次,共发现 30 条帖子。
是否继续滚动?(yes/no/再滚动 N 次)"
你: "再滚动 5 次"
代理: [滚动] → "共找到 80 条帖子。已保存至 feed.csv"你: "获取此目录中的所有产品"
代理: "我检测到分页:第 1 页,共 12 页。
可以抓取全部 12 页(耗时约 2-3 分钟),或部分页面。
需要多少页?"
你: "全部"
代理: [点击翻页 12 次] → "共 360 个产品,已保存至 catalog.csv"你: "抓取我的订单历史"
代理: "页面跳转至登录页。
我需要凭据才能继续。
请提供:
- 用户名/邮箱
- 密码
或输入 'skip' 以取消。"
你: "skip"
代理: "已取消。未提取任何数据。"You: "从这个页面获取价格"
Agent: "我发现了多种格式的价格:
- '$19.99'(美国格式)
- '€17.99'(欧洲格式)
- '¥2,980'(日本格式)
应该统一成哪种格式?"
You: "保持原样,增加一个 'currency' 列"
Agent: [执行货币识别并提取] → prices.csv
---
### 缺失或不一致的数据You: "从这个目录中提取员工数据"
Agent: "我看到共 100 张员工卡片。部分信息缺失:
- 12 个缺少电话号码
- 8 个缺少职位名称
- 3 个缺少照片
如何处理缺失字段?
A) 留空
B) 填写 'N/A'
C) 完全跳过这些行"
You: "B"
Agent: [提取 100 行数据,缺失字段用 'N/A' 填充] → employees.csv
---
## 自然语言指令
### `/scrape-to-csv <url> <描述>`
通用抓取并导出为 CSV。/scrape-to-csv https://news.ycombinator.com
"获取前 30 条新闻:标题、URL、得分、评论数"
/scrape-to-csv https://www.anthropic.com/news
"最新博客文章:标题、日期、分类、URL"
/scrape-to-csv https://example.com/realestate
"房源列表:地址、价格、卧室数、卫生间数、面积、经纪人"
### `/scrape-table <url> <选择器或描述>`
提取特定表格。/scrape-table https://example.com/pricing
"包含 Basic/Pro/Enterprise 列的对比表格"
/scrape-table https://example.com/sales
"2024 年第四季度营收分解表"
### `/scrape-news <url>`
专为新闻/博客抓取优化。/scrape-news https://techcrunch.com
"最新 20 篇文章:标题、作者、日期、摘要、URL"
/scrape-news https://blog.openai.com
"2024 年所有文章:标题、日期、标签、URL"
### `/scrape-products <url>`
专为电商场景优化。/scrape-products https://amazon.com/s?k=laptops
"笔记本电脑:名称、品牌、价格、评分、是否支持 Prime、URL"
/scrape-products https://shopify-store.com/collections/all
"所有商品:名称、价格、原价、库存状态"
---
## 输出格式
代理会生成结构化的 Markdown 报告:会话 ID: a1b2c3d4 | 耗时: 2分14秒 | 行数: 50
提取所有产品,包含名称、价格、评分和评论数量
| name | sale_price | rating | review_count | stock_status |
|---|---|---|---|---|
| Widget Pro | $999 | 4.5 | 128 | 在售 |
| Gadget Mini | $499 | 4.2 | 89 | 在售 |
| Super Gizmo | $1,299 | 4.8 | 256 | 无货 |
./products.csv — 50 行,5 列
---
## CSV 转换选项
### 选项 A — Python(推荐)import json, csv, re
msg = """PASTE_BRIDGE_RESPONSE_HERE"""
match = re.search(r'Result: (\[.*\])', msg)
if match:
data = json.loads(match.group(1))
with open('output.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
print(f"已写入 {len(data)} 行到 output.csv")
### 选项 B — Node.jsconst fs = require('fs');
const data = JSON.parse(fs.readFileSync('data.json', 'utf8'));
const headers = Object.keys(data[0]);
const csv = [
headers.join(','),
...data.map(row => headers.map(h => "${(row[h]||'').replace(/"/g,'""')}").join(','))
].join('\n');
fs.writeFileSync('output.csv', csv);
---
## 故障排除
### 桥接无法启动Error: Cannot find module 'playwright'
**解决方法:** `npm install -D playwright && npx playwright install chromium`
### 网站阻止抓取
**代理检测到:** "网站返回 403 Forbidden。可能是反爬虫机制。"
**可选方案:**
- 尝试设置 `headless: false`(更像真实用户行为)
- 在请求之间添加延迟
- 更换不同的 User Agent
### 页面加载但未发现数据
**代理检测到:** "页面已加载,但主要显示导航元素。内容可能需要登录或动态加载。"
**代理询问:** "是否需要等待更长时间、向下滚动,或者您有登录凭证吗?"
### 数据看起来异常
**代理检测到:** "价格显示为 'NaN' 或为空。网站可能使用 JavaScript 渲染价格。"
**代理询问:** "是否尝试执行 JavaScript 以提取真实值,还是跳过此字段?"
---
## 与其他工具对比
| 工具 | 配置方式 | 选择器需求 | 复杂页面处理 | 代理提问 | 适用场景 |
|------|-------|-----------|---------------|-----------------|----------|
| **Auto Scraping to CSV** | npm install | 无需 | 自动处理 | 是,澄清模糊点 | 一次性提取、探索性抓取 |
| BeautifulSoup | pip install | 必需 | 手动处理 | 否 | 已知结构、重复抓取 |
| Scrapy | 项目配置 | 必需 | 需要中间件 | 否 | 大规模爬取、数据管道 |
| Playwright E2E | npm install | 必需 | 手动处理 | 否 | 测试、自动化 |
| Browser-Use | API key | 无需 | 部分支持 | 有限 | 多页面研究 |
**使用本技能的场景包括:**
- 不想编写选择器即可抓取
- 页面结构复杂或未知
- 需要代理处理边缘情况(滚动、弹窗、分页)
- 数据存在歧义时需要澄清问题
- 快速完成一次性 CSV 导出
技能:自动抓取至 CSV
版本:1.0.1
分块:3/3
**响应:** `{ url, title, header, content, footer }`
### `POST /sessions/:id/act`
执行操作。
**请求体:**{ "action": "executeJavascript", "params": { "script": "return document.title;" } }
### `DELETE /sessions/:id`
关闭会话。
### `POST /shutdown`
停止桥接服务。
---
*技能:auto-scraping-to-csv v1.0.0 | 桥接:page-agent-bridge.mjs | 由 Alibaba Page-Agent + Playwright 驱动*已收录 1 个 Skill