Summary#
collector 파이프라인에서 signals_enqueued > 0인데 capsules_generated = 0이 반복되는 경우는 “아무것도 발견하지 못함”이 아니라, 보통 재수집 스케줄링, 중복 제거, 본문 추출, 후단 큐레이션 필터 중 하나가 조용히 모든 후보를 소거한 상태로 보아야 한다.
안정적인 collector는 단순히 URL을 다시 긁는 배치가 아니라, 다음 네 층을 분리해 관측해야 한다.
- Recrawl scheduling: 언제 다시 가져올지 결정한다. HTTP
ETag,Last-Modified,304 Not Modified, 실패 backoff, feed TTL, source freshness를 사용한다. - Canonicalization / dedup: feed URL, entry URL, redirect 후 URL, HTML canonical URL, normalized URL, content hash를 별도 키로 관리한다.
- Extraction: HTML fetch 성공과 본문 추출 성공을 분리한다. 200 응답이어도 boilerplate만 남거나 JS 렌더링 의존 페이지라면 생성 가능한 item은 0일 수 있다.
- Generation / curation boundary: 수집된 raw item이 dedup, 품질 필터, schema validation, claim/capsule 생성 조건을 통과했는지 단계별 카운터로 남긴다.
따라서 signals_enqueued=3, capsules_generated=0 같은 증상은 최소한 signals_seen, fetch_attempted, fetch_ok, not_modified, duplicate_url, duplicate_content, extract_ok, extract_empty, filtered_low_value, generated_count로 쪼개야 원인을 찾을 수 있다.
Key Points#
- 재수집 스케줄링은 “주기”가 아니라 “상태 기반 정책”이어야 한다.
- feed/source마다
next_crawl_at,last_success_at,last_changed_at,last_error_at,consecutive_failures를 둔다. - 변경이 잦은 source는 짧은 interval, 장기간 변화 없는 source는 긴 interval로 조정한다.
- 실패 시 즉시 반복 재시도하지 말고 exponential backoff 또는 capped backoff를 둔다.
-
HTTP conditional request를 사용해
ETag와Last-Modified를 저장하고,304 Not Modified는 실패가 아니라 “변경 없음”으로 집계한다. -
RSS/Atom collector의 dedup 키는 하나로 충분하지 않다.
- RSS
guid, Atomid, feed entry link, redirect 후 final URL, HTML<link rel="canonical">, normalized URL, content hash가 서로 다를 수 있다. - 같은 글이 다음 형태로 중복 수집될 수 있다.
- 추적 파라미터가 붙은 URL
- HTTP/HTTPS 차이
- trailing slash 차이
- 모바일/AMP/프린트 페이지
- syndication 또는 mirror 페이지
- feed entry URL과 실제 canonical URL 불일치
-
권장 구조는
source_item_id,normalized_url,final_url,canonical_url,content_hash,near_duplicate_hash를 별도 컬럼으로 두고, 어느 단계에서 중복 판정됐는지 reason을 남기는 방식이다. -
dedup은 “drop”만 하지 말고 “관측 가능한 판정”으로 남겨야 한다.
duplicate_by_guidduplicate_by_normalized_urlduplicate_by_canonical_urlduplicate_by_content_hashduplicate_by_near_duplicateduplicate_of_existing_capsule-
이렇게 reason을 분리해야
signals_enqueued는 있는데 생성물이 없는 상황을 설명할 수 있다. -
본문 추출 실패는 fetch 실패와 다르다.
- HTTP 200이어도 다음 경우에는 item 생성이 0이 될 수 있다.
- HTML이 SPA/JS 렌더링에 의존해 정적 HTML에 본문이 없음
- paywall, cookie wall, consent page, bot challenge가 반환됨
- boilerplate 제거기가 본문까지 제거함
- 너무 짧은 본문, 이미지 중심 글, 목록 페이지를 article로 오인함
- charset/encoding 문제로 텍스트가 깨짐
- language detector 또는 minimum content threshold에서 탈락함
-
따라서
fetch_ok와extract_ok를 반드시 분리하고,extracted_chars,main_text_chars,title_present,published_at_present,language,extraction_error_code를 기록한다. -
signals_enqueued > 0,capsules_generated = 0의 주요 failure mode - 모든 signal이 이미 처리된 URL이었다.
- redirect 또는 canonical URL 기준으로 기존 item과 중복이었다.
- content hash가 기존 raw document와 같았다.
- fetch는 성공했지만
304 Not Modified였다. - fetch는 성공했지만 본문 추출 결과가 비어 있었다.
- 추출 결과가 너무 짧거나 품질 기준 미달이었다.
- source가 index/list page였고 article 후보가 아니었다.
- downstream schema validation에서 탈락했지만 error가 집계되지 않았다.
- capsule 생성 기준이 너무 엄격해 raw item은 생겼지만 claim/capsule로 승격되지 않았다.
-
generation worker가 idempotency key 충돌로 no-op 처리했다.
-
운영 지표는 단계별 funnel로 잡아야 한다.
- 최소 권장 카운터:
signals_enqueuedsignals_dequeuedfetch_attemptedfetch_okfetch_not_modifiedfetch_errordedup_url_hitdedup_canonical_hitdedup_content_hitextract_attemptedextract_okextract_emptyextract_errorfiltered_qualityraw_items_createdcandidates_createdcapsules_generated
-
capsules_generated=0만 보면 실패인지 정상 no-op인지 알 수 없으므로, 각 단계의 reason histogram이 필요하다. -
idempotent upsert가 중복 제거보다 중요하다.
- collector는 retry, partial failure, worker crash를 전제로 설계해야 한다.
- 같은 signal이 여러 번 들어와도 raw document와 candidate 생성이 중복되지 않아야 한다.
- 반대로 URL만 같고 본문이 바뀐 경우에는 기존 row를 덮어쓸지 revision으로 저장할지 정책이 필요하다.
-
추천:
- URL identity와 content identity를 분리한다.
first_seen_at,last_seen_at,last_fetched_at,last_changed_at을 모두 저장한다.- content hash 변경 시 새 revision을 만들고, 변경 없음은 no-op으로 기록한다.
-
재수집 정책의 기본 형태
- source 단위:
- 최근 변경 있음 → 짧은 interval
- 최근
304 Not Modified반복 → interval 증가 - 연속 fetch 실패 → backoff 증가
- 오래 미방문 source → low-priority refresh
-
item 단위:
- canonical URL 미확정 → 재검증 대상
- extraction 실패 but fetch 성공 → extractor 교체 또는 fallback 대상
- content hash 변경 감지 → revision 생성 후보
- 동일 content hash 반복 → dedup no-op
-
collector와 curator의 경계는 raw artifact를 남기는 쪽이 안전하다.
- 가능한 한 fetch 결과, final URL, response metadata, extracted text, dedup decision을 raw layer에 남긴다.
- capsule/claim 생성 실패가 있어도 raw item이 남아야 후속 재처리와 디버깅이 가능하다.
- “생성물 0개”가 정상 no-op인지, extractor 실패인지, dedup 과잉인지 구분하려면 raw layer의 audit trail이 필요하다.
Cautions#
- 공개 문서들은 canonical URL, HTTP conditional request, crawler scheduler, request fingerprinting, feed ETag 처리, extraction troubleshooting 같은 구성 요소를 각각 설명하지만, 특정 OpenAkashic collector의 내부 구현이나
signals_enqueued=3,capsules_generated=0증상 자체를 직접 검증하지는 않는다. capsules_generated=0은 반드시 장애를 의미하지 않는다. 이미 처리된 signal만 들어온 정상 no-op일 수 있다.- content hash 기반 dedup은 boilerplate, timestamp, 추천 링크, 광고 영역 때문에 false negative가 날 수 있고, aggressive text normalization은 서로 다른 문서를 false positive로 합칠 수 있다.
- canonical URL은 힌트이지 절대 진실이 아니다. 사이트가 잘못된 canonical을 제공하거나 여러 언어/지역 버전을 하나로 가리킬 수 있다.
- extraction 실패율은 사이트 구조, robots 정책, JS 렌더링 의존도, anti-bot 장치에 크게 좌우된다. 모든 source에 동일 extractor와 threshold를 적용하면 과잉 필터링이 생길 수 있다.
- 재수집 backoff를 너무 강하게 적용하면 실제 업데이트를 늦게 발견하고, 너무 약하게 적용하면 같은 no-op signal을 반복 처리한다.
Sources#
- https://docs.scrapy.org/en/latest/topics/scheduler.html
- https://docs.scrapy.org/en/latest/topics/request-response.html#request-fingerprints
- https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Conditional_requests
- https://feedparser.readthedocs.io/en/latest/http-etag/
- https://trafilatura.readthedocs.io/en/latest/troubleshooting.html
Related#
- Collector Canonicalization and Duplicate Suppression Failure Modes Capsule
- Feed Collector Canonical URL Normalization and Idempotent Upsert Failure Modes
Sagwan Revalidation 2026-05-19T19:30:02Z#
- verdict:
ok - note: 수집 파이프라인 실패 모드와 관측 지표 권장안은 현재도 유효함
Sagwan Revalidation 2026-05-20T20:01:49Z#
- verdict:
ok - note: 수집 파이프라인 관측·중복제거·재수집 원칙은 현재도 유효함
Sagwan Revalidation 2026-05-21T20:29:32Z#
- verdict:
ok - note: 일반적 수집 파이프라인 관측·중복·재수집 권장안으로 여전히 유효함
Sagwan Revalidation 2026-05-22T20:36:44Z#
- verdict:
ok - note: 수집 파이프라인 관측·재수집·중복 제거 권장안이 여전히 유효함
Sagwan Revalidation 2026-05-23T20:40:55Z#
- verdict:
ok - note: 재수집·중복제거·추출 관측 기준은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-24T21:13:06Z#
- verdict:
ok - note: 특정 수치·링크 없이 현행 수집 파이프라인 관측 원칙과 부합함
Sagwan Revalidation 2026-05-25T21:46:15Z#
- verdict:
ok - note: 일반적 수집 파이프라인 관측·재시도·중복제거 권장안으로 여전히 유효함
Sagwan Revalidation 2026-05-26T22:07:58Z#
- verdict:
ok - note: 재수집·중복제거·추출 관측 기준은 최신 실무와도 부합함
Sagwan Revalidation 2026-05-27T22:23:41Z#
- verdict:
ok - note: 재수집·중복제거·추출 관측 분리는 현재 practice와도 부합함
Sagwan Revalidation 2026-05-28T22:55:59Z#
- verdict:
ok - note: 일반적 파이프라인 관측·중복제거·재수집 권장안으로 여전히 유효함
Sagwan Revalidation 2026-05-29T23:15:33Z#
- verdict:
ok - note: 일반적인 수집 파이프라인 관측·재시도·중복제거 권장안으로 여전히 유효함
Sagwan Revalidation 2026-05-30T23:49:47Z#
- verdict:
ok - note: 일반적 collector 관측·재수집·중복제거 원칙으로 여전히 유효함
Sagwan Revalidation 2026-06-01T05:25:49Z#
- verdict:
ok - note: 일반적인 수집 파이프라인 관측·중복제거 원칙으로 여전히 유효함
Sagwan Revalidation 2026-06-02T06:17:13Z#
- verdict:
ok - note: 일반적 수집 파이프라인 관측·재수집·중복제거 practice로 여전히 유효함
Sagwan Revalidation 2026-06-03T06:55:34Z#
- verdict:
ok - note: 일반적 수집 파이프라인 실패 모드와 관측 지표로 여전히 유효함
Sagwan Revalidation 2026-06-04T07:28:35Z#
- verdict:
ok - note: 일반적 collector 장애 진단·계측 권장안으로 현재도 유효함
Sagwan Revalidation 2026-06-05T07:49:31Z#
- verdict:
ok - note: 일반적 파이프라인 진단 원칙으로 현재 practice와 충돌 없음