1. 引言

OpenClaw 是一个轻量级、高性能的网页抓取框架,专为需要快速构建稳定爬虫的开发者设计。它基于 Python 异步编程模型,内置了请求重试、代理轮换、数据解析和结果导出等常用功能,让你能专注于业务逻辑而非底层细节。

本文将带你从环境搭建开始,逐步深入到实际抓取案例,通过完整的代码实操,让你快速掌握 OpenClaw 的核心用法。

2. 环境准备与安装

2.1 系统要求

  • Python 3.8 及以上版本
  • 支持 Windows、macOS、Linux

2.2 安装 OpenClaw

推荐使用 pip 在虚拟环境中安装:

# 创建虚拟环境(可选但推荐)
python -m venv openclaw_env
source openclaw_env/bin/activate  # Linux/macOS
# openclaw_env\Scripts\activate  # Windows

# 安装 OpenClaw
pip install openclaw

验证安装是否成功:

import openclaw
print(openclaw.__version__)
# 预期输出类似:0.2.1

3. 第一个抓取任务:抓取静态页面

我们从最简单的场景开始——抓取一个静态 HTML 页面并提取标题和所有链接。

3.1 创建爬虫脚本

新建文件 first_spider.py

import asyncio
from openclaw import Spider, Request, Item

class MyFirstSpider(Spider):
    name = "first_spider"
    
    # 起始 URL 列表
    start_urls = ["https://example.com"]
    
    async def parse(self, response):
        """解析响应,提取数据"""
        # 提取页面标题
        title = response.css("title::text").get()
        
        # 提取所有链接
        links = response.css("a::attr(href)").getall()
        
        # 返回一个 Item 对象
        yield Item({
            "title": title,
            "url": response.url,
            "links": links,
        })

# 运行爬虫
if __name__ == "__main__":
    spider = MyFirstSpider()
    asyncio.run(spider.run())

3.2 运行并查看结果

python first_spider.py

运行后,你会在终端看到类似输出:

[2026-07-19 16:00:00] INFO: Spider 'first_spider' started
[2026-07-19 16:00:01] INFO: Crawled (200) https://example.com
[2026-07-19 16:00:01] INFO: Item scraped: {'title': 'Example Domain', 'url': 'https://example.com', 'links': ['https://www.iana.org/domains/example']}
[2026-07-19 16:00:01] INFO: Spider 'first_spider' finished

默认情况下,抓取到的 Item 会以 JSON 格式输出到控制台。你也可以配置导出到文件。

4. 核心概念详解

4.1 Spider(爬虫)

Spider 是核心类,你需要继承它并定义:

  • name:爬虫的唯一标识
  • start_urls:起始抓取地址
  • parse 方法:处理响应的回调函数

4.2 Request(请求)

Request 对象封装了一次 HTTP 请求的所有参数:

from openclaw import Request

# 基本用法
req = Request(url="https://example.com/page/2", callback=self.parse_page)

# 带参数的请求
req = Request(
    url="https://api.example.com/data",
    method="POST",
    headers={"Authorization": "Bearer your_token"},
    body='{"key": "value"}',
    callback=self.parse_api
)

4.3 Item(数据项)

Item 是结构化数据的容器,通常用字典形式创建:

from openclaw import Item

# 简单 Item
item = Item({"name": "Alice", "age": 30})

# 嵌套 Item
item = Item({
    "product": {
        "name": "Laptop",
        "price": 999.99,
        "specs": ["16GB RAM", "512GB SSD"]
    }
})

4.4 Response(响应)

Response 对象提供了多种数据提取方式:

# CSS 选择器
response.css("div.content p::text").get()
response.css("div.item").getall()

# XPath 选择器
response.xpath("//div[@class='content']/p/text()").get()
response.xpath("//a/@href").getall()

# 正则表达式
response.re(r"价格:(\d+\.\d{2})")
response.re_first(r"订单号:([A-Z0-9]+)")

5. 实战案例:抓取电商商品列表

现在我们来做一个更贴近实际的案例——抓取一个模拟电商网站的商品列表,并处理分页。

5.1 目标分析

假设我们要抓取 https://books.toscrape.com/(一个专门用于练习爬虫的图书网站),需要提取:

  • 每本书的标题、价格、库存状态
  • 翻页抓取所有商品

5.2 完整代码

创建 book_spider.py

import asyncio
from openclaw import Spider, Request, Item

class BookSpider(Spider):
    name = "book_spider"
    start_urls = ["https://books.toscrape.com/"]
    
    async def parse(self, response):
        """解析列表页"""
        books = response.css("article.product_pod")
        
        for book in books:
            # 提取单本书信息
            title = book.css("h3 a::attr(title)").get()
            price = book.css("p.price_color::text").get()
            stock = book.css("p.instock.availability::text").get()
            
            # 获取详情页链接
            detail_url = book.css("h3 a::attr(href)").get()
            if detail_url:
                # 拼接完整 URL
                full_url = response.urljoin(detail_url)
                # 发起详情页请求,并传递已提取的数据
                yield Request(
                    url=full_url,
                    callback=self.parse_detail,
                    meta={"title": title, "price": price, "stock": stock}
                )
        
        # 处理分页
        next_page = response.css("li.next a::attr(href)").get()
        if next_page:
            next_url = response.urljoin(next_page)
            yield Request(url=next_url, callback=self.parse)
    
    async def parse_detail(self, response):
        """解析详情页,提取更多信息"""
        # 从 meta 中获取列表页已提取的数据
        title = response.meta["title"]
        price = response.meta["price"]
        stock = response.meta["stock"]
        
        # 提取详情页特有的数据
        description = response.css("meta[name='description']::attr(content)").get()
        upc = response.xpath("//th[text()='UPC']/following-sibling::td/text()").get()
        
        yield Item({
            "title": title,
            "price": price,
            "stock": stock.strip() if stock else None,
            "description": description.strip() if description else None,
            "upc": upc,
            "detail_url": response.url,
        })

if __name__ == "__main__":
    spider = BookSpider()
    asyncio.run(spider.run())

5.3 运行与结果导出

# 运行爬虫,并将结果保存到 JSON 文件
python book_spider.py -o books.json

查看 books.json 文件,你会看到类似这样的结构化数据:

[
  {
    "title": "A Light in the Attic",
    "price": "£51.77",
    "stock": "In stock",
    "description": "It's hard to imagine a world without A Light in the Attic.",
    "upc": "a897fe39b8b0c8b9",
    "detail_url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
  },
  ...
]

6. 高级功能

6.1 配置中间件

OpenClaw 支持通过中间件实现请求重试、代理轮换、User-Agent 随机化等功能:

# config.py
from openclaw import Settings

settings = Settings()
settings.set("DOWNLOAD_DELAY", 1.5)  # 请求间隔 1.5 秒
settings.set("RETRY_TIMES", 3)       # 失败重试 3 次
settings.set("CONCURRENT_REQUESTS", 8)  # 并发请求数
settings.set("USER_AGENT", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
settings.set("PROXY_ENABLED", True)
settings.set("PROXY_LIST", [
    "http://proxy1.example.com:8080",
    "http://proxy2.example.com:8080",
])

在爬虫中加载配置:

class MySpider(Spider):
    name = "my_spider"
    custom_settings = {
        "DOWNLOAD_DELAY": 2.0,
        "CONCURRENT_REQUESTS": 4,
    }
    # ...

6.2 数据管道(Pipeline)

Pipeline 用于对抓取到的 Item 进行后处理,如清洗、去重、存储到数据库:

# pipelines.py
import json

class JsonPipeline:
    """将 Item 写入 JSON 文件"""
    def __init__(self):
        self.items = []
    
    async def process_item(self, item):
        self.items.append(dict(item))
        return item
    
    async def close_spider(self):
        with open("output.json", "w", encoding="utf-8") as f:
            json.dump(self.items, f, ensure_ascii=False, indent=2)

class DuplicatesPipeline:
    """去重 Pipeline"""
    def __init__(self):
        self.seen = set()
    
    async def process_item(self, item):
        if item["title"] in self.seen:
            raise DropItem(f"Duplicate item: {item['title']}")
        self.seen.add(item["title"])
        return item

在爬虫中启用 Pipeline:

class MySpider(Spider):
    name = "my_spider"
    pipelines = [JsonPipeline(), DuplicatesPipeline()]
    # ...

6.3 处理 JavaScript 渲染页面

对于动态加载的页面,OpenClaw 支持集成 Playwright:

from openclaw import Spider, Request
from openclaw.downloader import PlaywrightDownloader

class JsSpider(Spider):
    name = "js_spider"
    downloader = PlaywrightDownloader()  # 使用 Playwright 下载器
    
    async def parse(self, response):
        # 此时 response 已经是 JavaScript 渲染后的完整 HTML
        title = response.css("h1::text").get()
        yield Item({"title": title})

7. 常见问题与调试技巧

7.1 请求被屏蔽

  • 降低请求频率:设置 DOWNLOAD_DELAY
  • 随机化 User-Agent:使用中间件随机切换
  • 使用代理 IP:配置 PROXY_LIST
  • 添加 Cookie:在 Request 中传入 cookies 参数

7.2 调试日志

import logging
logging.basicConfig(level=logging.DEBUG)  # 开启 DEBUG 日志

7.3 断点续爬

OpenClaw 支持请求队列持久化,中断后可以继续:

spider = MySpider()
spider.run(job_dir="./crawl_jobs")  # 指定作业目录,支持断点续爬

8. 总结

本文从零开始,通过多个实操案例详细介绍了 OpenClaw 的使用方法:

  1. 环境搭建:安装与验证
  2. 基础用法:抓取静态页面,提取数据
  3. 核心概念:Spider、Request、Item、Response
  4. 实战案例:电商商品列表抓取,含分页处理
  5. 高级功能:中间件、Pipeline、JS 渲染
  6. 调试技巧:反爬应对、日志、断点续爬

OpenClaw 的设计哲学是「简单但不简陋」,它提供了足够丰富的功能来应对大多数抓取场景,同时保持了代码的简洁和可读性。建议你从本文的示例开始,逐步修改和扩展,在实践中掌握它的精髓。

更多推荐