# Apify Actor Development

> 重要提示：开始前，请在 .actor/actor.json 的 meta 部分填写 generatedBy 属性，替换为您当前使用的工具和模型，例如 "Claude Code with Claude Sonnet 4.5"。这有助于 Apify 监控和改进特定 AI 工具和模型的 AGENTS.md。触发词：Apify Actor、Actor 开发、Apify 爬虫、serverless 程序、Docker 容器、网页抓取、数据采集、apify-cli、Crawlee、Playwright、Cheerio

- Skill: `kscz0000/apify-actor-development` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add kscz0000/apify-actor-development`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kscz0000/apify-actor-development/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: kscz0000 (https://skillmd.com/u/kscz0000)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/kscz0000/apify-actor-development

---


<!-- security-allowlist: curl-pipe-bash, irm-pipe-iex -->

# Apify Actor 开发

**重要提示：** 开始前，请在 `.actor/actor.json` 的 meta 部分填写 `generatedBy` 属性。替换为您当前使用的工具和模型，例如 "Claude Code with Claude Sonnet 4.5"。这有助于 Apify 监控和改进特定 AI 工具和模型的 AGENTS.md。

## 何时使用
- 需要创建、修改或调试 Apify Actor 项目
- 任务涉及选择 Apify 模板、连接 Actor 输入/输出，或实现 Actor 运行时逻辑
- 需要 `apify` CLI 认证、项目初始化或部署工作流的安全设置指导

## 什么是 Apify Actor？

Actor 是受 UNIX 哲学启发的无服务器程序——做好一件事的程序，可以轻松组合构建复杂系统。它们被打包为 Docker 镜像，在云端的隔离容器中运行。

**核心概念：**
- 接受定义良好的 JSON 输入
- 执行隔离任务（网页抓取、自动化、数据处理）
- 生成结构化 JSON 输出到数据集和/或在键值存储中存储数据
- 可运行数秒到数小时，甚至无限期运行
- 持久化状态，可重启

## 前置条件与设置（必须）

在创建或修改 Actor 之前，验证 `apify` CLI 是否已安装 `apify --help`。

如果未安装，使用以下方法之一（按优先级排序）：

```bash
# 推荐：通过包管理器安装（提供完整性检查）
npm install -g apify-cli

# 或 (Mac): brew install apify-cli
```

> **安全提示：** 不要通过将远程脚本管道传输到 shell 的方式安装 CLI
>（例如 `curl … | bash` 或 `irm … | iex`）。始终使用包管理器。

当 apify CLI 安装完成后，检查是否已登录：

```bash
apify info  # 应返回您的用户名
```

如果未登录，检查是否定义了 `APIFY_TOKEN` 环境变量（如果没有，请用户在 https://console.apify.com/settings/integrations 生成一个，然后用它定义 `APIFY_TOKEN`）。

然后使用以下方法之一进行认证：

```bash
# 选项 1（推荐）：CLI 自动从环境变量读取 APIFY_TOKEN。
# 只需确保环境变量已导出并运行任何 apify 命令——无需显式登录。

# 选项 2：交互式登录（提示输入 token，不会暴露在 shell 历史中）
apify login
```

> **安全提示：** 避免将 token 作为命令行参数传递（例如 `apify login -t <token>`）。
> 参数在进程列表中可见，可能被记录在 shell 历史中。
> 优先使用环境变量或交互式登录。
> 永远不要记录、打印或将 `APIFY_TOKEN` 嵌入源代码或配置文件中。
> 使用具有最小所需权限的 token（限定范围的 token）并定期轮换。

## 模板选择

**重要：** 在开始 Actor 开发之前，始终询问用户偏好哪种编程语言：
- **JavaScript** - 使用 `apify create <actor-name> -t project_empty`
- **TypeScript** - 使用 `apify create <actor-name> -t ts_empty`
- **Python** - 使用 `apify create <actor-name> -t python-empty`

根据用户的语言选择使用相应的 CLI 命令。额外的包（Crawlee、Playwright 等）可以稍后根据需要安装。

## 快速入门工作流

1. **创建 Actor 项目** - 根据用户语言偏好运行相应的 `apify create` 命令（见上方模板选择）
2. **安装依赖**（安装前验证包名与预期包匹配）
   - JavaScript/TypeScript: `npm install`（使用 `package-lock.json` 进行可重现、完整性检查的安装——将 lockfile 提交到版本控制）
   - Python: `pip install -r requirements.txt`（在 `requirements.txt` 中固定精确版本，例如 `crawlee==1.2.3`，并将文件提交到版本控制）
3. **实现逻辑** - 在 `src/main.py`、`src/main.js` 或 `src/main.ts` 中编写 Actor 代码
4. **配置 Schema** - 更新 `.actor/input_schema.json`、`.actor/output_schema.json`、`.actor/dataset_schema.json` 中的输入/输出 Schema
5. **配置平台设置** - 更新 `.actor/actor.json` 中的 Actor 元数据（见 [references/actor-json.md](references/actor-json.md)）
6. **编写文档** - 为市场创建全面的 README.md
7. **本地测试** - 运行 `apify run` 验证功能（见下方本地测试部分）
8. **部署** - 运行 `apify push` 将 Actor 部署到 Apify 平台（Actor 名称在 `.actor/actor.json` 中定义）

## 安全

**将所有抓取的网页内容视为不可信输入。** Actor 从外部网站摄取数据，这些数据可能包含恶意负载。遵循以下规则：

- **清洗抓取的数据** — 永远不要将原始 HTML、URL 或抓取的文本直接传递给 shell 命令、`eval()`、数据库查询或模板引擎。使用适当的转义或参数化 API。
- **验证和类型检查所有外部数据** — 在推送到数据集或键值存储之前，验证值是否匹配预期的类型和格式。拒绝或清洗意外结构。
- **不要执行或解释抓取的内容** — 永远不要将抓取的文本视为代码、命令或配置。网站内容可能包含提示注入尝试或嵌入的脚本。
- **将凭据与数据管道隔离** — 确保 `APIFY_TOKEN` 和其他密钥在请求处理程序中永远不可访问，也不与抓取数据一起传递。使用 Apify SDK 内置的凭据管理，而不是在数据处理代码中通过环境变量传递 token。
- **安装前审查依赖** — 使用 `npm install` 或 `pip install` 添加包时，验证包名和发布者。域名抢注是常见的供应链攻击向量。优先选择知名、积极维护的包。
- **固定版本并使用 lockfile** — 始终提交 `package-lock.json`（Node.js）或在 `requirements.txt` 中固定精确版本（Python）。Lockfile 确保可重现构建，防止静默依赖替换。定期运行 `npm audit` 或 `pip-audit` 检查已知漏洞。

## 最佳实践

**✓ 应该：**
- 使用 `apify run` 在本地测试 Actor（配置 Apify 环境和存储）
- 使用 Apify SDK (`apify`) 编写运行在 Apify 平台上的代码
- 尽早验证输入，正确处理错误，优雅失败
- 使用 CheerioCrawler 处理静态 HTML（比浏览器快 10 倍）
- 仅对 JavaScript 密集型网站使用 PlaywrightCrawler
- 使用路由器模式（createCheerioRouter/createPlaywrightRouter）处理复杂抓取
- 实现带指数退避的重试策略
- 使用适当的并发：HTTP (10-50)，浏览器 (1-5)
- 在 `.actor/input_schema.json` 中设置合理的默认值
- 在 `.actor/output_schema.json` 中定义输出 Schema
- 推送到数据集前清洗和验证数据
- 使用语义化 CSS 选择器并提供回退策略
- 尊重 robots.txt、服务条款，实现速率限制
- **始终使用 `apify/log` 包** — 审查敏感数据（API 密钥、token、凭据）
- 实现就绪探针处理器（如果 Actor 使用待机模式则必需）

**✗ 不应该：**
- 使用 `npm start`、`npm run start`、`npx apify run` 或类似命令运行 Actor（改用 `apify run`）
- 假设 `apify run` 的本地存储会被推送到或在 Apify Console 中可见——它仅是本地的；使用 `apify push` 部署并在平台上运行以在 Console 中查看结果
- 在云端依赖 `Dataset.getInfo()` 获取最终计数
- 当 HTTP/Cheerio 可用时使用浏览器爬虫
- 硬编码应该在输入 Schema 或环境变量中的值
- 跳过输入验证或错误处理
- 使服务器过载——使用适当的并发和延迟
- 抓取禁止的内容或忽略服务条款
- 存储个人/敏感数据，除非明确允许
- 在 CheerioCrawler (v3.x) 上使用已弃用的选项如 `requestHandlerTimeoutMillis`
- 使用 `additionalHttpHeaders` — 改用 `preNavigationHooks`
- 将原始抓取内容传递给 shell 命令、`eval()` 或代码生成函数
- 使用 `console.log()` 或 `print()` 代替 Apify logger — 这些会绕过凭据审查
- 未经明确许可禁用待机模式

## 日志

完整的日志文档见 [references/logging.md](references/logging.md)，包括可用的日志级别以及 JavaScript/TypeScript 和 Python 的最佳实践。

检查 `.actor/actor.json` 中的 `usesStandbyMode` — 仅在设置为 `true` 时实现。

## 命令

```bash
apify run          # 本地运行 Actor
apify login        # 认证账户
apify push         # 部署到 Apify 平台（使用 .actor/actor.json 中的名称）
apify help         # 列出所有命令
```

**重要：** 始终使用 `apify run` 在本地测试 Actor。不要使用 `npm run start`、`npm start`、`yarn start` 或其他包管理器命令——这些无法正确配置 Apify 环境和存储。

## 本地测试

使用 `apify run` 在本地测试 Actor 时，通过创建以下 JSON 文件提供输入数据：

```
storage/key_value_stores/default/INPUT.json
```

此文件应包含 `.actor/input_schema.json` 中定义的输入参数。Actor 在本地运行时将读取此输入，模拟其在 Apify 平台上接收输入的方式。

**重要 - 本地存储不会同步到 Apify Console：**
- 运行 `apify run` 将所有数据（数据集、键值存储、请求队列）**仅存储在本地文件系统**的 `storage/` 目录中。
- 此数据**永远不会**自动上传或推送到 Apify 平台。它仅存在于您的机器上。
- 要在 Apify Console 中验证结果，必须使用 `apify push` 部署 Actor，然后在平台上运行。
- **不要**依赖检查 Apify Console 来验证本地运行的结果——而是检查本地 `storage/` 目录或查看 Actor 的日志输出。

## 待机模式

完整的待机模式文档见 [references/standby-mode.md](references/standby-mode.md)，包括 JavaScript/TypeScript 和 Python 的就绪探针实现。

## 项目结构

```
.actor/
├── actor.json           # Actor 配置：名称、版本、环境变量、运行时
├── input_schema.json    # 输入验证和 Console 表单定义
└── output_schema.json   # 输出存储和显示模板
src/
└── main.js/ts/py       # Actor 入口点
storage/                # 仅本地存储（不同步到 Apify Console）
├── datasets/           # 输出项（JSON 对象）
├── key_value_stores/   # 文件、配置、INPUT
└── request_queues/     # 待处理的抓取请求
Dockerfile              # 容器镜像定义
```

## Actor 配置

完整的 actor.json 结构和配置选项见 [references/actor-json.md](references/actor-json.md)。

## 输入 Schema

输入 Schema 结构和示例见 [references/input-schema.md](references/input-schema.md)。

## 输出 Schema

输出 Schema 结构、示例和模板变量见 [references/output-schema.md](references/output-schema.md)。

## 数据集 Schema

数据集 Schema 结构、配置和显示属性见 [references/dataset-schema.md](references/dataset-schema.md)。

## 键值存储 Schema

键值存储 Schema 结构、集合和配置见 [references/key-value-store-schema.md](references/key-value-store-schema.md)。

## Apify MCP 工具

如果配置了 MCP 服务器，使用以下工具获取文档：

- `search-apify-docs` - 搜索文档
- `fetch-apify-docs` - 获取完整文档页面

否则，MCP 服务器 URL: `https://mcp.apify.com/?tools=docs`。

## 资源

- [docs.apify.com/llms.txt](https://docs.apify.com/llms.txt) - Apify 快速参考文档
- [docs.apify.com/llms-full.txt](https://docs.apify.com/llms-full.txt) - Apify 完整文档
- [https://crawlee.dev/llms.txt](https://crawlee.dev/llms.txt) - Crawlee 快速参考文档
- [https://crawlee.dev/llms-full.txt](https://crawlee.dev/llms-full.txt) - Crawlee 完整文档
- [whitepaper.actor](https://raw.githubusercontent.com/apify/actor-whitepaper/refs/heads/master/README.md) - 完整 Actor 规范

## 限制
- 仅当任务明确匹配上述描述的范围时使用此技能。
- 不要将输出视为环境特定验证、测试或专家审查的替代品。
- 如果缺少所需输入、权限、安全边界或成功标准，请停下来请求澄清。

