> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel FullFeed

> 피드 리더용으로 웹 페이지의 메인 콘텐츠를 추출하는 Laravel 패키지. Laravel의 Pipeline 패턴을 활용.

## 개요

[revolution/laravel-fullfeed](https://github.com/invokable/laravel-fullfeed)는 피드 리더용으로 웹 페이지에서 본문을 추출하는 Laravel 패키지입니다.\
사이트별 룰(JSON)을 사용하여 각 기사에 필요한 콘텐츠를 추출합니다.

<Info>
  원래는 프라이빗한 피드 리더 앱에서 사용되던 기능이 분리되어 공개 패키지화되어 있습니다.
</Info>

## 요구 사항

* PHP >= 8.4(`Dom\HTMLDocument`를 이용)
* Laravel >= 12.x

## 설치

```bash theme={null}
composer require revolution/laravel-fullfeed
```

개발 버전을 사용하는 경우:

```bash theme={null}
composer require revolution/laravel-fullfeed:dev-main
```

## 설정 파일과 사이트 정의 공개

```bash theme={null}
php artisan vendor:publish --tag=fullfeed
```

이 명령어로 다음이 생성됩니다.

* `config/fullfeed.php`
* `resources/fullfeed`

## 정의 파일 자동 갱신(composer post-update-cmd)

`composer update` 시에 사이트 정의를 자동으로 재공개하려면 `composer.json`에 다음을 추가합니다.

```json theme={null}
{
  "scripts": {
    "post-update-cmd": [
      "@php artisan vendor:publish --tag=laravel-assets --ansi --force",
      "@php artisan vendor:publish --tag=fullfeed-site --ansi --force"
    ]
  }
}
```

## 기본적인 사용법

```php theme={null}
use Revolution\Fullfeed\Facades\FullFeed;

$html = FullFeed::get($url);
```

## 테스트

`FullFeed::expects()`로 Facade를 스텁할 수 있습니다.

```php theme={null}
use Revolution\Fullfeed\Facades\FullFeed;

FullFeed::expects('get')
    ->with('https://example.com/article/1')
    ->andReturn('<div>Main content</div>');
```

## 사이트 룰 파일

### items\_all.json

`items_all.json`은 LDRFullFeed(wedata) 형식의 룰을 가져오기 위한 베이스입니다.\
Livedoor Reader는 일본에서 유명한 서비스였지만 서비스 자체는 종료되었으며, 현재는 룰 데이터가 주로 자산으로 남아 있습니다. FullFeed는 이 역사적인 데이터 형식을 활용합니다.

### plus.json

`plus.json`은 자체 룰 추가용 샘플입니다.

```json theme={null}
{
  "name": "note",
  "data": {
    "url": "^https://note\\.com/",
    "selector": "div[data-name=\"body\"]",
    "xpath": "//div[@data-name=\"body\"]",
    "enc": "UTF-8",
    "callable": "App\\FullFeed\\CustomExtractor"
  }
}
```

## 룰 설정 필드

* `url`: 대상 URL에 매칭시키는 정규 표현식
* `selector`: CSS 셀렉터(`xpath`보다 우선)
* `xpath`: XPath 지정
* `enc`: 문자 코드 변환이 필요한 경우의 인코딩 지정
* `callable`: 전처리로 실행할 자체 Extractor 클래스(단일/배열)
* `after_callable`: 후처리로 마지막에 실행할 Extractor 클래스

## Pipeline 패턴으로서의 Extractor 실행 순서

FullFeed는 Laravel의 **Pipeline 패턴**으로, Extractor를 순서대로 흘려보냅니다.

1. `callable`에서 지정한 클래스
2. `XPathExtractor`
3. `SelectorExtractor`
4. `after_callable`에서 지정한 클래스

단순한 XPath/CSS 추출 전후에 자체 처리를 삽입할 수 있으므로, 사이트별 특이 사항에 대응하기 쉬운 설계입니다.

## 내장 Extractor

### RemoveElements

지정한 셀렉터의 요소를 삭제합니다.

```json theme={null}
{
  "after_callable": ["Revolution\\Fullfeed\\Extractor\\RemoveElements"],
  "remove": ["svg", "button", "script"]
}
```

### ReplaceMatches

정규 표현식으로 일치한 문자열을 치환합니다(HTML 문자열에 대해 처리).

```json theme={null}
{
  "after_callable": ["Revolution\\Fullfeed\\Extractor\\ReplaceMatches"],
  "replace": [
    {
      "pattern": "/ data-(h-)?index=\"[0-9]+\"/",
      "replace": ""
    }
  ]
}
```

### StripTags

`strip_tags()` 상당으로 태그를 제거합니다.

```json theme={null}
{
  "after_callable": ["Revolution\\Fullfeed\\Extractor\\StripTags:a,img"]
}
```

### Squish

`Str::squish()`로 여분의 공백을 제거합니다.

```json theme={null}
{
  "after_callable": ["Revolution\\Fullfeed\\Extractor\\Squish"]
}
```

## 자체 룰 추가

1. `resources/fullfeed`에 JSON 파일을 추가
2. `config/fullfeed.php`의 `paths`에 추가

`data.url`에 가장 먼저 매칭한 룰이 사용되므로, 추가 파일은 `paths`의 맨 앞에 두는 것을 권장합니다.


## Related topics

- [Feed Generator](/ko/packages/laravel-bluesky/feed-generator.md)
- [Feedable](/ko/packages/feedable/index.md)
- [지원 사이트 목록 - Feedable](/ko/packages/feedable/drivers.md)
- [테스트](/ko/packages/laravel-bluesky/testing.md)
- [코어 패키지와 커스텀 드라이버 - Feedable](/ko/packages/feedable/core.md)
