PHPackages                             changhorizon/content-collector - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. changhorizon/content-collector

ActiveLibrary[Queues &amp; Workers](/categories/queues)

changhorizon/content-collector
==============================

A safety-first Laravel crawler with task lifecycle, SSRF protection, and job-based architecture

0.4.0(3mo ago)01MITPHPPHP ^8.2CI passing

Since Jan 30Pushed 3mo agoCompare

[ Source](https://github.com/changhorizon/content-collector)[ Packagist](https://packagist.org/packages/changhorizon/content-collector)[ Docs](https://github.com/changhorizon/content-collector)[ RSS](/packages/changhorizon-content-collector/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (10)Versions (12)Used By (0)

📦 Content Collector
===================

[](#-content-collector)

[![License](https://camo.githubusercontent.com/cf9ad035adf9a1621a483410bee724a9fa57bb80e43f751a88651f3a2d5a2a0f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6368616e67686f72697a6f6e2f636f6e74656e742d636f6c6c6563746f723f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/cf9ad035adf9a1621a483410bee724a9fa57bb80e43f751a88651f3a2d5a2a0f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6368616e67686f72697a6f6e2f636f6e74656e742d636f6c6c6563746f723f7374796c653d666c61742d737175617265)[![Latest Version](https://camo.githubusercontent.com/2a9d2c7033e4d51a9f2c95cbecaee2e8de2c4e1dd4eaebc29a272dae928bf692/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6368616e67686f72697a6f6e2f636f6e74656e742d636f6c6c6563746f723f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/2a9d2c7033e4d51a9f2c95cbecaee2e8de2c4e1dd4eaebc29a272dae928bf692/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6368616e67686f72697a6f6e2f636f6e74656e742d636f6c6c6563746f723f7374796c653d666c61742d737175617265)[![PHP Version](https://camo.githubusercontent.com/10b897c523f00fa3f8f7b54dfe73999190e622480655d5b5f011e31fc32a7111/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d382e322d2d382e342d626c75653f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/10b897c523f00fa3f8f7b54dfe73999190e622480655d5b5f011e31fc32a7111/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d382e322d2d382e342d626c75653f7374796c653d666c61742d737175617265)[![CI](https://github.com/changhorizon/content-collector/actions/workflows/tests.yml/badge.svg?branch=main&style=flat-square)](https://github.com/changhorizon/content-collector/actions/workflows/tests.yml/badge.svg?branch=main&style=flat-square)

A safety-first Laravel crawler designed for controlled, trusted targets, with explicit task lifecycle, job idempotency and built-in SSRF protection.

✨ 特性
----

[](#-特性)

- 多 Job 并发爬取（Fetch / Parse / Media 解耦）
- 严格 URL Policy，防 SSRF
- Task 生命周期明确（start → completed）
- Redis 可选，自动 DB 回退（行为一致）
- Job 幂等，安全可重试
- 数据库是最终一致性的真实状态源（Redis 仅作为加速器）

安装
--

[](#安装)

```
composer require changhorizon/content-collector
php artisan vendor:publish --tag=content-collector-config
php artisan vendor:publish --tag=content-collector-migrations
php artisan migrate
```

> 本包依赖 Laravel Queue，请确保已配置并运行 queue worker

🚀 快速使用
------

[](#-快速使用)

```
use ChangHorizon\ContentCollector\Services\Crawler;

Crawler::run([
   'confine' => [
      'max_urls' => 10000,
   ],
   'site' => [
      'entry' => 'https://example.com',
   ],
]);
```

🔄 爬虫流程（架构约束）
------------

[](#-爬虫流程架构约束)

爬虫遵循严格的、以数据库为中心的流程：

1. **抓取**

    - 始终生成一个 `RawPage` 记录作为爬取事实。
    - 原始 HTML 被存储并作为唯一数据源。
2. **解析**

    - 从数据库读取原始 HTML，而不是作业有效负载。
    - 如果存在原始内容，则始终尝试解析。
3. **持久化（策略控制）**

    - `ContentPersistencePolicy` 决定是否持久化已解析的结果（例如 `ParsedPage`、`Reference`）。
    - 无论是否持久化，都会记录解析完成情况。

> RawPage 始终作为抓取与解析阶段的唯一事实源存在。

🧠 核心概念
------

[](#-核心概念)

Task（一次爬取）

- 每次 Crawler::run() 生成一个 task\_id
- Task 的完成条件：
    - 所有 RawPage.fetched\_at 均不为 null
    - 即：系统只关心「是否尝试过抓取」，而非抓取是否成功

❗ 完成 ≠ 内容 100% 成功

失败、被拒绝、404 都是真实结果，不会阻塞 Task 完成。

### Job 说明

[](#job-说明)

Job职责FetchPageJobHTTP 获取页面（产生 RawPage 事实）ParsePageJob解析 HTML，提取 links / metaDownloadMediaJob下载媒体资源> ⚠️ 只有 FetchPageJob 会触发 Task 完成检查

🔐 安全策略（重要）
----------

[](#-安全策略重要)

### URL Policy（默认）

[](#url-policy默认)

- ❌ 禁止 localhost / 127.0.0.1
- ❌ 禁止私有 IP
- ❌ 禁止 file:// / javascript:
- ❌ 禁止跨 host（默认）

> 所有 URL 在 Fetch 前校验

### SSRF 防护

[](#ssrf-防护)

- DNS 解析结果校验
- IP 段白 / 黑名单
- Scheme 白名单

> ⚠️ SSRF 防护为强制策略，无法通过配置完全关闭

⚖️ 并发与 Redis 回退
---------------

[](#️-并发与-redis-回退)

- Redis 不是必需
- Redis 不可用时：
    - 自动使用 DB 行锁
    - 性能下降，但行为一致（已测试）

> 无需额外配置。

🧪 测试策略
------

[](#-测试策略)

- 只测试：
    - Task 生命周期
    - Job 幂等
    - Redis 回退行为
    - URL Policy 与 Ledger 约束
- 不测试：
    - HTML 解析细节
    - Laravel Queue 行为

⚠️ 使用约束（必须读）
------------

[](#️-使用约束必须读)

以下为设计层面的明确约束，而非未来待改进事项：

- ❌ 不适合超大规模分布式爬虫
- ❌ 不保证实时性
- ❌ 不保证媒体下载成功率
- ✅ 适合 受控、可信目标站点

🛠 设计原则（供维护者）
------------

[](#-设计原则供维护者)

- 数据库是最终真相
- Job 必须幂等
- Redis 只能是加速器
- 失败优雅、完成明确
- 宁可少功能，不要隐性状态

### 内容持久化策略

[](#内容持久化策略)

`ContentPersistencePolicy` 仅控制是否持久化**派生内容**（已解析的页面、引用）。 它**不**影响抓取、原始存储或爬取计划。

> 解析任务不再承载原始 HTML 有效负载。 所有解析均基于持久化的原始页面执行。

📌 迁移与升级提示
---------

[](#-迁移与升级提示)

- 不要修改 migration
- 如需扩展字段，使用新 migration
- Job / Task 语义不可破坏

📄 License
---------

[](#-license)

MIT License. See the [LICENSE](LICENSE) file for details.

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance82

Actively maintained with recent releases

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

11

Last Release

97d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ebedf625b7a40647c79c0b4788067638b60eb50ed9d0cab47ea0852e03772020?d=identicon)[changhorizon](/maintainers/changhorizon)

---

Top Contributors

[![changhorizon](https://avatars.githubusercontent.com/u/191742660?v=4)](https://github.com/changhorizon "changhorizon (25 commits)")

---

Tags

laravelcrawlerqueuejobweb-scrapercontent-collector

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/changhorizon-content-collector/health.svg)

```
[![Health](https://phpackages.com/badges/changhorizon-content-collector/health.svg)](https://phpackages.com/packages/changhorizon-content-collector)
```

###  Alternatives

[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k84.2M225](/packages/laravel-horizon)[imtigger/laravel-job-status

Laravel Job Status

5272.1M3](/packages/imtigger-laravel-job-status)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

3786.5k](/packages/harris21-laravel-fuse)[maqe/laravel-sqs-fifo

Laravel package that enables support for SQS FIFO Queue

15137.2k](/packages/maqe-laravel-sqs-fifo)[pmatseykanets/artisan-beans

Easily manage your Beanstalkd job queues right from the Laravel artisan command

4482.1k](/packages/pmatseykanets-artisan-beans)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
