在 GitHub 已获得 84 个星标,且数量仍在增加。Yozh Crawler + Scraper 是一款免费、开源且公开开发的工具——如果它能成为您技术栈中的一员,请给我们点个星标
CyberYozh Data / 用例 / 网页抓取与分析
用例 · 网页抓取

面向 SQL 结构化的公开网络数据

将任何公开页面或整个网站的数据以纯净的 JSON 格式导入您的数据仓库:职位信息、新闻、评论、产品目录、公开个人资料等。Yozh 负责处理选择器、反机器人措施、重试和代理——您的加载器只需将数据追加到 Snowflake、BigQuery 或 Postgres 中即可。

$curl -s :8000/api/v1/scrape/batch -d @urls.json | jq -c '.results[]' | psql -c "COPY raw FROM stdin"
batch: g2.com/products
Target table
scraped_pages
Batch
200 urls 8 workers 1.0/s
Status
streaming · 247 / 200 rows
Yozh batch /scrape/batch
Pulling URL batch
Stealth fetch + retry
Parsing & normalizing
Emitting JSON-lines
COPY FROM stdin
管道连接至 你的栈
为什么大多数管道会腐蚀

DIY数据抓取工具占用了90%的分析时间,并输出不规范的数据

一个“小小的 Python 脚本”,却演变成了长达数月的 Cookie 轮换、代理轮换、选择器修复、重试队列,以及凌晨 3 点因源头更改了一个类名而收到的警报。数据团队整个季度都在重构基础架构,而不是开发仪表盘。 我们开箱即用地提供了每个团队都需要从头重建的四个组件。

如果您的仓库在源系统重新设计后, null列数多于行数,那么这篇文章就是为您准备的。

易碎的自制刮刀在四分之一时间内就腐烂了

问题在于:一个原本只是周末闲暇时写的 Python 脚本,竟演变成一个脆弱的内部引擎:这里有个队列,那里有个重试层,缺乏可观测性,还有一个每当源代码重新设计时就会失效的 CSS 选择器。团队被迫维护着一套他们原本根本不想编写的基础设施。

Yozh Scraper 是如何解决这一问题的。生产就绪型引擎:并行批处理执行器、采用指数退避的自动重试、结构化错误代码,以及能够根据实时 DOM 重新生成损坏选择器的 LLM 自愈功能。仅需一行 docker compose up 即可取代数月的工作量。

  • LLM 自我修复
  • 批处理 + 重试
  • 结构化错误

所有源文件中都充斥着混乱的HTML代码

问题在于:每个网站返回的数据都各不相同,包含嵌套的 div 标签、未记录的 JSON 数据块以及不一致的日期格式。你的加载器在进入数据仓库之前需要一个标准化步骤——而每当源网站进行改版时,这个步骤总是最先出问题。

Yozh Scraper 是如何解决这一问题的。内置预设可在不同数据源中返回完全一致的 JSON 结构——相同的键名、ISO 日期格式、经过区域设置规范化的货币单位。自定义数据源? POST /api/v1/presets/generate 只需提供一个示例 URL——大型语言模型(LLM)便会推断出数据结构并生成选择器。可直接嵌入到 COPY ... FROM stdin.

  • 统一 JSON 结构
  • ISO 日期
  • LLM 生成的预设

反机器人措施蚕食了冲刺时间

问题在于:数据中心代理在一次会话中就会过载,验证码屏障会在任务进行到一半时阻断爬取,TLS 指纹识别能在几秒内识别出无头浏览器。数据工程师最终只能忙于排查阻塞问题,而非构建仪表盘。代理费用激增,而爬取量却停滞不前。

Yozh Scraper 是如何解决这一问题的。通过以下方式与 CyberYozh App Proxy 原生集成 CYBERYOZH_API_KEY — 覆盖 250 个国家代码的 5 种代理类型(住宅轮换/固定、移动 4G/5G、数据中心、ISP)。采用隐身版 Chromium 构建,通过温指纹自动匹配代理源头。绝大多数流量都不会遇到 CAPTCHA 验证。

  • 5 种代理类型
  • 250 个国家代码
  • 预热指纹

临时爬取协调

问题在于:“遍历该网站,抓取每个产品页面,监控新出现的URL”在逻辑上是一个任务——但在代码实现中,它涉及队列、去重表、作用域规则、RPS限制以及两阶段取消机制。如果手动实现,在重试过程中系统会出错,并会悄无声息地重新抓取相同的URL。

Yozh Scraper 是如何解决这一问题的。Yozh Crawler 在服务器端遍历网站,通过每个任务的 SHA1 哈希值进行去重,将新 URL 通过 SSE 流式传输,并在每次匹配时将其传递给抓取器。采用两阶段取消机制(软取消 → 强制取消)。 将数据流直接导入 Airflow / dbt / cron —— 编排工作仍由您现有的工具负责。

  • SSE 流式传输
  • 按任务去重
  • Airflow / dbt / cron
工作原理

从原始网页到仓库货架——只需3步

提取一个端点,加载一个形状。将 Yozh 直接接入您现有的加载器、协调器或数据仓库——无需中间层。

1 让引擎轰鸣起来

克隆该仓库,然后 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
2 批量抓取一组URL

通过 POST 提交您的 URL 批次(每次调用最多 200 个)。工作进程并行运行,重试和代理均在服务器端处理。所有数据源返回相同的 JSON 结构。

curl 
  localhost:8000/api/v1/scrape/batch 
  -X POST 
  -d '{"urls": ["…", "…"],
       "preset": "auto",
       "concurrency": 8}'
3 直接输送到您的仓库

结果以 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"
实时示例

您将获得什么——一种形式,适配所有市场

选择一个预设,查看响应效果。字段集因来源而异,但请求结构完全相同。


            
使用范例

数据团队是如何构建系统的——每人10行代码

从页面到仓库的三条具体流水线,已准备就绪,随时可用。Yozh 负责抓取工作——您的调度器负责安排日程。

1 每日快照 → Postgres

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+
200 个 URL/批 COPY FROM stdin 你的 cron / Airflow
2 探索爬取 → BigQuery

爬取网站,在发现新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
SSE 流式传输 按任务去重 (SHA1) 仅增量插入
3 新闻数据流 → Kafka

爬取并抓取新闻来源,将每篇文章作为 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
抓取 + 发布链路 Kafka 生产者 每个源一个 topic
FAQ

关于将数据抓取到数据仓库的常见问题

我可以抓取哪些数据源?
任何公开页面。内置预设涵盖了流量最大的页面——电商平台、搜索引擎、YouTube、LinkedIn个人主页(含会话)。对于自定义来源,只需调用 POST /api/v1/presets/generate 并提供一个示例 URL——大型语言模型(LLM)将推断出数据结构并生成选择器,您将在几秒内获得一个可重复使用的预设。对于一次性页面, POST /scrape/page 使用显式 extract: {...} 模式,即使没有预设也能正常工作。系统默认遵守 Robots.txt 规则;对于非您所有的来源,请务必遵守该规则。
如何将数据导入 Snowflake / BigQuery / Postgres?
该爬虫在每次批处理时返回 JSON 行,在每次爬取时返回 SSE 流。可直接将其导入您的数据仓库加载器: jq -c '.results[]' | psql -c "COPY raw FROM stdin" 对于 Postgres, bq insert 针对 BigQuery, snowsql --query "PUT ..." + COPY INTO 适用于 Snowflake,或写入 S3/GCS,并让现有的 Snowpipe 或外部表进行读取。无需维护定制连接器——它只是通过 HTTP 传输的 JSON。
我可以在我的 VPC 内运行这个吗?
是的——Yozh 支持自主部署。 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 指标开箱即用。
它与 Airflow / dbt / Temporal 如何配合使用?
Yozh 负责数据抓取;您的调度器负责安排任务。最简单的模式:一个 Airflow BashOperator (或带有 requests) 调用 /scrape/batch,将结果导入暂存表,随后在下游串联一个 dbt 任务。爬取操作会返回一个 SSE 流——可使用长期运行的任务,或通过 job_id将其拆分为可恢复的块。没有捆绑的调度器意味着没有锁定:直接使用您的数据平台现有的任何调度器即可。
开源 · MIT 许可 · 84 ★

准备好将网页数据导入您的数据仓库了吗?

只需一个 Docker Compose 文件,一个 JSON-lines 数据流,所有数据源均经过标准化处理——直接导入 Snowflake、BigQuery、Postgres 和 Kafka。免费。永久免费。如果对您有帮助,请为我们点个星——每一个星都至关重要。

Yozh Crawler + Scraper 根据 MIT 许可证发布。请随意使用、分叉和基于它进行开发。

深受数据团队和人工智能开发者的喜爱

使用 Yozh 进行开发的用户怎么说

5.0 / 5 · 5 评测
GitHub
仅用一个下午就将我们内部的 Playwright 集群替换为 Yozh。MCP 端点直接接入我们的 Claude 代理——无需任何胶水代码,爬虫和数据提取工具便能正常运行。
Marcus Reinhardt 首席数据工程师 Northwind Analytics
X
预设系统是其杀手级功能。我们传入源名称,就能得到干净的 JSON 数据;其自动修复功能甚至在我们察觉之前就发现了亚马逊的两次布局变更。
Priya Nair 创始人 ScrapeStack
Reddit
终于出现了一个将代理和会话视为第一类对象的开源爬虫工具。我们将其部署在合作伙伴门户网站的登录墙后方——会话能够保持持久性,且跨区域的爬取结果始终保持一致。
Daniel Osei 后端工程师 Loopfeed
X
通过 MCP 将其连接到 Cursor 后,我的代理现在可以在任务进行中实时提取网页数据。通过 SSE 进行的流式爬取,正是代理工作流所缺失的功能。
Elena Kovac 人工智能工程师 Vektor Labs
GitHub
为了节省成本,我们放弃了付费的数据抓取 API,并做好了性能下降的准备——结果却事与愿违。现在采用自托管模式,无需按请求付费,而且输出数据结构比我们以前付费使用的还要简洁。
Sofia Almeida 工程经理 Tabbly