将任何公开页面或整个网站的数据以纯净的 JSON 格式导入您的数据仓库:职位信息、新闻、评论、产品目录、公开个人资料等。Yozh 负责处理选择器、反机器人措施、重试和代理——您的加载器只需将数据追加到 Snowflake、BigQuery 或 Postgres 中即可。
curl -s :8000/api/v1/scrape/batch -d @urls.json
| jq -c '.results[]' | psql -c "COPY raw FROM stdin"
一个“小小的 Python 脚本”,却演变成了长达数月的 Cookie 轮换、代理轮换、选择器修复、重试队列,以及凌晨 3 点因源头更改了一个类名而收到的警报。数据团队整个季度都在重构基础架构,而不是开发仪表盘。 我们开箱即用地提供了每个团队都需要从头重建的四个组件。
如果您的仓库在源系统重新设计后, null列数多于行数,那么这篇文章就是为您准备的。
提取一个端点,加载一个形状。将 Yozh 直接接入您现有的加载器、协调器或数据仓库——无需中间层。
克隆该仓库,然后 docker compose up。爬虫运行于 :8000,爬虫已就绪 :8001。无需 SaaS 账户,无需 API 密钥向导——在您的 VPC 上运行。
# one-time setup
git clone
github.com/CyberYozh-data/yozh-scraper
cd yozh-scraper
docker compose up -d
通过 POST 提交您的 URL 批次(每次调用最多 200 个)。工作进程并行运行,重试和代理均在服务器端处理。所有数据源返回相同的 JSON 结构。
curl
localhost:8000/api/v1/scrape/batch
-X POST
-d '{"urls": ["…", "…"],
"preset": "auto",
"concurrency": 8}'
结果以 JSON 行形式输出。通过 jq 导入 COPY ... FROM stdin ,或通过 Snowflake / BigQuery 客户端直接加载。无需中间件。
# postgres example curl :8000/api/v1/scrape/batch -d @urls.json | jq -c '.results[]' | psql -c "COPY raw FROM stdin"
选择一个预设,查看响应效果。字段集因来源而异,但请求结构完全相同。
从页面到仓库的三条具体流水线,已准备就绪,随时可用。Yozh 负责抓取工作——您的调度器负责安排日程。
Cron 提取一个 URL 列表,进行批量抓取,并将 JSON 数据行直接流式传输到临时表中。dbt 在下游处理这些数据。
# crontab: every day at 06:00 0 6 * * * /usr/local/bin/snapshot.sh # snapshot.sh curl -s :8000/api/v1/scrape/batch -d "@urls.json" | jq -c '.results[]' | psql -c "COPY raw_scrape FROM stdin" # dbt build runs next in Airflow DAG dbt build --select staging.raw_scrape+
爬取网站,在发现新URL时实时流式传输。与昨日数据进行去重,仅抓取新增内容,并在数据到达时将其插入BigQuery。
# stream discovered URLs over SSE curl -N :8001/api/v1/crawl/start -d '{"seed_url":"site.com", "scope":"same-domain", "max_pages":1000}' | jq -r 'select(.event=="found") | .url' | comm -13 yesterday.txt - | bq insert dataset.urls --source_format=NEWLINE_DELIMITED_JSON
爬取并抓取新闻来源,将每篇文章作为 Kafka 事件发布。下游消费者(仪表盘、情感分析模型、警报系统)按主题订阅。
# 1. continuous crawl of source list curl -N :8001/api/v1/crawl/start -d "@sources.json" | jq -c 'select(.event=="scraped") | .result' | kcat -P -t news.raw -b kafka:9092 # 2. consumers subscribe downstream kcat -C -t news.raw | your-pipeline
POST /api/v1/presets/generate 并提供一个示例 URL——大型语言模型(LLM)将推断出数据结构并生成选择器,您将在几秒内获得一个可重复使用的预设。对于一次性页面, POST /scrape/page 使用显式 extract: {...} 模式,即使没有预设也能正常工作。系统默认遵守 Robots.txt 规则;对于非您所有的来源,请务必遵守该规则。jq -c '.results[]' | psql -c "COPY raw FROM stdin" 对于 Postgres, bq insert 针对 BigQuery, snowsql --query "PUT ..." + COPY INTO 适用于 Snowflake,或写入 S3/GCS,并让现有的 Snowpipe 或外部表进行读取。无需维护定制连接器——它只是通过 HTTP 传输的 JSON。docker compose up 它会在您指定的任何网络环境(VPC、本地部署、物理隔离网络)中部署两个容器(抓取器 + 爬虫)。 不向服务器发送回传数据,不依赖 SaaS 服务。出站流量仅流向您要抓取的目标(如果您启用了该功能,则可选地流向 CyberYozh App Proxy)。日志、跟踪信息和指标将保留在您指定的位置——Prometheus 端点位于 /metrics,结构化 JSON 日志则输出到标准输出(stdout)。BLOCKED, CAPTCHA, SELECTOR_FAIL, UPSTREAM_TIMEOUT ——因此您的加载器可以基于这些代码进行分支处理,而无需解析字符串。当源代码重构导致选择器失效时,LLM 自愈机制会即时重新生成它(传递 llm: {model: "..."}) 并为响应添加 self_heal: true 以便下游进行审计。队列深度、成功率和代理延迟的 Prometheus 指标开箱即用。BashOperator (或带有 requests) 调用 /scrape/batch,将结果导入暂存表,随后在下游串联一个 dbt 任务。爬取操作会返回一个 SSE 流——可使用长期运行的任务,或通过 job_id将其拆分为可恢复的块。没有捆绑的调度器意味着没有锁定:直接使用您的数据平台现有的任何调度器即可。只需一个 Docker Compose 文件,一个 JSON-lines 数据流,所有数据源均经过标准化处理——直接导入 Snowflake、BigQuery、Postgres 和 Kafka。免费。永久免费。如果对您有帮助,请为我们点个星——每一个星都至关重要。
Yozh Crawler + Scraper 根据 MIT 许可证发布。请随意使用、分叉和基于它进行开发。
使用 Yozh 进行开发的用户怎么说
仅用一个下午就将我们内部的 Playwright 集群替换为 Yozh。MCP 端点直接接入我们的 Claude 代理——无需任何胶水代码,爬虫和数据提取工具便能正常运行。
预设系统是其杀手级功能。我们传入源名称,就能得到干净的 JSON 数据;其自动修复功能甚至在我们察觉之前就发现了亚马逊的两次布局变更。
终于出现了一个将代理和会话视为第一类对象的开源爬虫工具。我们将其部署在合作伙伴门户网站的登录墙后方——会话能够保持持久性,且跨区域的爬取结果始终保持一致。
通过 MCP 将其连接到 Cursor 后,我的代理现在可以在任务进行中实时提取网页数据。通过 SSE 进行的流式爬取,正是代理工作流所缺失的功能。
为了节省成本,我们放弃了付费的数据抓取 API,并做好了性能下降的准备——结果却事与愿违。现在采用自托管模式,无需按请求付费,而且输出数据结构比我们以前付费使用的还要简洁。