目录
-
- 摘要
- [1. 引言 - 数据采集的价值](#1. 引言 - 数据采集的价值)
-
- [1.1 数据采集应用场景](#1.1 数据采集应用场景)
- [1.2 OpenClaw 数据采集优势](#1.2 OpenClaw 数据采集优势)
- [1.3 数据采集流程](#1.3 数据采集流程)
- [2. 静态页面抓取](#2. 静态页面抓取)
-
- [2.1 使用 web_fetch](#2.1 使用 web_fetch)
- [2.2 web_fetch 参数](#2.2 web_fetch 参数)
- [2.3 实战:抓取文章内容](#2.3 实战:抓取文章内容)
- [2.4 实战:批量抓取](#2.4 实战:批量抓取)
- [3. 动态页面抓取](#3. 动态页面抓取)
-
- [3.1 使用 Browser 工具](#3.1 使用 Browser 工具)
- [3.2 处理无限滚动](#3.2 处理无限滚动)
- [3.3 处理分页](#3.3 处理分页)
- [4. 实战案例一:电商商品信息抓取](#4. 实战案例一:电商商品信息抓取)
-
- [4.1 场景描述](#4.1 场景描述)
- [4.2 实现代码](#4.2 实现代码)
- [4.3 批量抓取商品](#4.3 批量抓取商品)
- [5. 实战案例二:新闻文章抓取](#5. 实战案例二:新闻文章抓取)
-
- [5.1 场景描述](#5.1 场景描述)
- [5.2 实现代码](#5.2 实现代码)
- [6. 实战案例三:社交媒体数据抓取](#6. 实战案例三:社交媒体数据抓取)
-
- [6.1 场景描述](#6.1 场景描述)
- [6.2 实现代码](#6.2 实现代码)
- [7. 反爬虫应对](#7. 反爬虫应对)
-
- [7.1 常见反爬机制](#7.1 常见反爬机制)
- [7.2 应对策略](#7.2 应对策略)
- [7.3 检测被封](#7.3 检测被封)
- [8. 数据清洗与存储](#8. 数据清洗与存储)
-
- [8.1 数据清洗](#8.1 数据清洗)
- [8.2 数据存储](#8.2 数据存储)
- [8.3 数据去重](#8.3 数据去重)
- [9. 最佳实践](#9. 最佳实践)
-
- [9.1 抓取策略](#9.1 抓取策略)
- [9.2 礼貌爬虫原则](#9.2 礼貌爬虫原则)
- [9.3 代码模板](#9.3 代码模板)
- [10. 总结](#10. 总结)
-
- [10.1 核心要点](#10.1 核心要点)
- [10.2 工具选择](#10.2 工具选择)
- [10.3 下一步](#10.3 下一步)
- 参考资料
摘要
本文通过实际案例演示 OpenClaw 的网页数据抓取能力。从静态页面抓取、动态内容处理到大规模数据采集,全面解析数据采集的实现技巧。涵盖反爬虫应对、数据清洗、存储导出等关键环节,帮助开发者构建高效可靠的数据采集解决方案。📊
1. 引言 - 数据采集的价值
1.1 数据采集应用场景
| 场景 |
说明 |
数据类型 |
| 价格监控 |
电商价格对比 |
商品价格、库存 |
| 舆情分析 |
社交媒体监控 |
评论、帖子 |
| 竞品分析 |
竞争对手研究 |
产品信息、策略 |
| 内容聚合 |
信息整合平台 |
文章、新闻 |
| 研究分析 |
学术研究数据 |
论文、报告 |
1.2 OpenClaw 数据采集优势
OpenClaw
描述需求
AI自动抓取
智能解析
自动存储
传统爬虫
编写代码
处理反爬
解析数据
存储数据
1.3 数据采集流程
| 步骤 |
说明 |
工具 |
| 访问页面 |
打开目标网页 |
browser |
| 获取内容 |
抓取页面数据 |
snapshot/web_fetch |
| 解析数据 |
提取结构化信息 |
AI解析 |
| 存储数据 |
保存到文件/数据库 |
write |
2. 静态页面抓取
2.1 使用 web_fetch
# 简单的网页内容获取
result = web_fetch(
url="https://example.com/article",
extractMode="markdown" # 或 "text"
)
2.2 web_fetch 参数
| 参数 |
类型 |
说明 |
| url |
string |
目标URL |
| extractMode |
string |
提取模式:markdown/text |
| maxChars |
number |
最大字符数 |
2.3 实战:抓取文章内容
def fetch_article(url):
"""抓取文章内容"""
# 获取网页内容
content = web_fetch(
url=url,
extractMode="markdown",
maxChars=10000
)
# AI 自动解析
# 返回的是结构化的 markdown 内容
return content
2.4 实战:批量抓取
def batch_fetch(urls):
"""批量抓取多个页面"""
results = []
for url in urls:
try:
content = web_fetch(
url=url,
extractMode="markdown"
)
results.append({
"url": url,
"content": content,
"status": "success"
})
except Exception as e:
results.append({
"url": url,
"error": str(e),
"status": "failed"
})
# 礼貌延迟,避免被封
time.sleep(1)
return results
3. 动态页面抓取
3.1 使用 Browser 工具
动态页面需要使用 Browser 工具,因为它可以执行 JavaScript。
def fetch_dynamic_page(url):
"""抓取动态页面"""
# 1. 打开页面
browser(action="open", targetUrl=url)
# 2. 等待动态内容加载
browser(action="act", kind="wait", timeMs=3000)
# 3. 获取快照
snapshot = browser(action="snapshot")
# 4. 从快照中提取数据
data = extract_data_from_snapshot(snapshot)
return data
3.2 处理无限滚动
def fetch_infinite_scroll(url, max_scrolls=10):
"""处理无限滚动页面"""
browser(action="open", targetUrl=url)
all_data = []
previous_count = 0
for i in range(max_scrolls):
# 获取当前数据
snapshot = browser(action="snapshot")
current_data = extract_items(snapshot)
all_data.extend(current_data)
# 检查是否有新数据
if len(current_data) == previous_count:
break
previous_count = len(current_data)
# 滚动加载更多
browser(action="act", kind="scroll", y=1000)
browser(action="act", kind="wait", timeMs=2000)
# 去重
unique_data = deduplicate(all_data)
return unique_data
3.3 处理分页
def fetch_paginated(base_url, max_pages=10):
"""处理分页数据"""
all_data = []
for page in range(1, max_pages + 1):
url = f"{base_url}?page={page}"
browser(action="open", targetUrl=url)
browser(action="act", kind="wait", timeMs=2000)
snapshot = browser(action="snapshot")
page_data = extract_items(snapshot)
if not page_data:
break
all_data.extend(page_data)
return all_data
4. 实战案例一:电商商品信息抓取
4.1 场景描述
从电商网站抓取商品信息,包括名称、价格、评价数等。
4.2 实现代码
def scrape_product_info(url):
"""抓取商品信息"""
# 1. 打开商品页面
browser(action="open", targetUrl=url)
browser(action="act", kind="wait", timeMs=3000)
# 2. 获取页面快照
snapshot = browser(action="snapshot")
# 3. 提取商品信息
product = {
"url": url,
"name": extract_product_name(snapshot),
"price": extract_price(snapshot),
"rating": extract_rating(snapshot),
"reviews": extract_review_count(snapshot),
"stock": extract_stock_status(snapshot),
"images": extract_image_urls(snapshot)
}
return product
def extract_product_name(snapshot):
"""提取商品名称"""
# 查找标题元素
for element in snapshot["elements"]:
if element.get("type") == "heading" and element.get("level") == 1:
return element.get("text", "")
return ""
def extract_price(snapshot):
"""提取价格"""
# 查找价格元素(通常包含 ¥ 或 $ 符号)
for element in snapshot["elements"]:
text = element.get("text", "")
if "¥" in text or "$" in text:
# 清理价格文本
price = re.sub(r"[^\d.]", "", text)
return float(price) if price else None
return None
4.3 批量抓取商品
def scrape_multiple_products(urls):
"""批量抓取多个商品"""
products = []
for url in urls:
try:
product = scrape_product_info(url)
products.append(product)
print(f"成功: {product['name']}")
except Exception as e:
print(f"失败: {url} - {e}")
# 随机延迟,避免被封
time.sleep(random.uniform(1, 3))
# 保存结果
save_to_json(products, "products.json")
return products
5. 实战案例二:新闻文章抓取
5.1 场景描述
从新闻网站抓取文章列表和内容。
5.2 实现代码
def scrape_news_site(base_url):
"""抓取新闻网站"""
# 1. 打开新闻列表页
browser(action="open", targetUrl=base_url)
browser(action="act", kind="wait", timeMs=2000)
# 2. 获取文章列表
snapshot = browser(action="snapshot")
article_links = extract_article_links(snapshot)
# 3. 抓取每篇文章
articles = []
for link in article_links[:10]: # 限制数量
article = scrape_article(link)
articles.append(article)
time.sleep(1)
return articles
def extract_article_links(snapshot):
"""提取文章链接"""
links = []
for element in snapshot["elements"]:
if element.get("type") == "link":
href = element.get("href", "")
if is_article_link(href):
links.append(href)
return links
def scrape_article(url):
"""抓取单篇文章"""
# 使用 web_fetch 更高效
content = web_fetch(url=url, extractMode="markdown")
# AI 自动解析标题、正文、作者等
return {
"url": url,
"content": content,
"scraped_at": datetime.now().isoformat()
}
6. 实战案例三:社交媒体数据抓取
6.1 场景描述
从社交媒体抓取用户帖子或评论。
6.2 实现代码
def scrape_social_media(url):
"""抓取社交媒体数据"""
# 1. 打开页面
browser(action="open", targetUrl=url)
browser(action="act", kind="wait", timeMs=3000)
# 2. 滚动加载更多内容
for _ in range(5):
browser(action="act", kind="scroll", y=500)
browser(action="act", kind="wait", timeMs=1000)
# 3. 获取快照
snapshot = browser(action="snapshot")
# 4. 提取帖子/评论
posts = []
for element in snapshot["elements"]:
if is_post_element(element):
posts.append({
"author": extract_author(element),
"content": extract_content(element),
"time": extract_time(element),
"likes": extract_likes(element)
})
return posts
7. 反爬虫应对
7.1 常见反爬机制
| 机制 |
说明 |
应对策略 |
| User-Agent检测 |
检测浏览器标识 |
设置真实UA |
| 请求频率限制 |
限制请求速度 |
随机延迟 |
| IP封禁 |
封禁异常IP |
代理IP池 |
| 验证码 |
人机验证 |
OCR/人工 |
| 动态内容 |
JS渲染 |
使用Browser |
7.2 应对策略
def safe_scrape(url):
"""安全的抓取策略"""
# 1. 随机延迟
time.sleep(random.uniform(2, 5))
# 2. 模拟人类行为
browser(action="open", targetUrl=url)
# 随机滚动
browser(action="act", kind="scroll", y=random.randint(100, 300))
browser(action="act", kind="wait", timeMs=random.randint(1000, 3000))
# 3. 获取数据
snapshot = browser(action="snapshot")
return snapshot
7.3 检测被封
def check_blocked(snapshot):
"""检测是否被封"""
# 检查是否有验证码
if find_element(snapshot, "image", "验证码"):
return "captcha"
# 检查是否有错误提示
if find_element(snapshot, "text", "访问频繁"):
return "rate_limited"
if find_element(snapshot, "text", "IP"):
return "ip_blocked"
return None
8. 数据清洗与存储
8.1 数据清洗
def clean_data(raw_data):
"""清洗数据"""
cleaned = []
for item in raw_data:
# 去除空白字符
for key, value in item.items():
if isinstance(value, str):
item[key] = value.strip()
# 去除HTML标签
if "content" in item:
item["content"] = remove_html_tags(item["content"])
# 格式化日期
if "date" in item:
item["date"] = normalize_date(item["date"])
cleaned.append(item)
return cleaned
8.2 数据存储
def save_to_json(data, filename):
"""保存为JSON"""
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def save_to_csv(data, filename):
"""保存为CSV"""
if not data:
return
with open(filename, 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
def save_to_excel(data, filename):
"""保存为Excel"""
import pandas as pd
df = pd.DataFrame(data)
df.to_excel(filename, index=False)
8.3 数据去重
def deduplicate(data, key_field="url"):
"""数据去重"""
seen = set()
unique = []
for item in data:
key = item.get(key_field)
if key and key not in seen:
seen.add(key)
unique.append(item)
return unique
9. 最佳实践
9.1 抓取策略
| 策略 |
说明 |
| 先小后大 |
先测试少量数据 |
| 增量抓取 |
只抓取新数据 |
| 错误重试 |
失败后重试 |
| 断点续传 |
记录进度 |
9.2 礼貌爬虫原则
| 原则 |
说明 |
| 遵守robots.txt |
尊重网站规则 |
| 控制频率 |
不给服务器压力 |
| 标识身份 |
设置联系信息 |
| 合理时间 |
避开高峰期 |
9.3 代码模板
def polite_scrape(url):
"""礼貌的抓取"""
# 1. 检查 robots.txt
if not is_allowed_by_robots(url):
raise Exception("robots.txt 禁止抓取")
# 2. 随机延迟
time.sleep(random.uniform(1, 3))
# 3. 抓取数据
try:
data = web_fetch(url=url)
return data
except Exception as e:
print(f"抓取失败: {e}")
return None
10. 总结
10.1 核心要点
| 要点 |
说明 |
| 选择工具 |
静态用web_fetch,动态用browser |
| 控制频率 |
避免被封禁 |
| 数据清洗 |
确保数据质量 |
| 合规抓取 |
遵守网站规则 |
10.2 工具选择
| 场景 |
推荐工具 |
| 静态页面 |
web_fetch |
| 动态页面 |
browser |
| 大量数据 |
browser + 增量抓取 |
| 需要登录 |
browser + chrome扩展 |
10.3 下一步
- 第51篇:OpenClaw Canvas:可视化界面入门
- 第52篇:OpenClaw Canvas 导航:URL 加载与控制
参考资料