복잡한 운동 웹사이트용 축구 코치 연락처 추출기 구축 방법
I’m happy to translate the article for you, but I’ll need the full text of the post (the part you want translated) in order to do so. Could you please paste the article content here? Once I have it, I’ll provide the Korean translation while keeping the source link, formatting, markdown, and any code blocks exactly as they appear.
개요
대부분의 체육 웹사이트는 대규모로 구조화된 데이터를 추출하려고 할 때까지는 단순해 보입니다.
코치 페이지는 특히 난잡합니다:
- 한 학교는
mailto:링크가 포함된 깔끔한 직원 디렉터리를 제공합니다. - 다른 학교는 이메일을 Cloudflare 뒤에 숨깁니다.
- 또 다른 학교는 명단 페이지에 이름만 올리고 실제 연락처 정보는 별도의 프로필 페이지에 둡니다.
- 또 다른 경우는 빈 셸을 반환하고 나머지는 JavaScript가 처리하도록 기대합니다.
이것이 이 프로젝트가 해결하는 문제입니다.
football-soccer-emails는 TypeScript‑기반 추출기로, 체육 웹사이트에서 축구 및 풋볼 코치 연락 정보를 가져와 구조화된 레코드로 변환합니다. 다음을 지원합니다:
- 직접 URL
- 공개 Google 스프레드시트
- 배치 실행을 위한 Apify 워크플로
왜 이 접근법인가?
나는 2017‑2018년에 이 문제를 순수히 휴리스틱만 사용해 해결했으며, 약 40 % 정확도를 달성했다. 규칙만으로는 한계에 부딪혔다.
LLM과 다단계 추출 흐름을 도입하면, 동일한 유형의 문제에서도 이제 90 % 이상의 정확도를 얻을 수 있다.
이 프로젝트는 단일 추출 방법에 의존하지 않는다. 세 가지 교체 가능한 전략을 제공한다:
| 전략 | 설명 |
|---|---|
| heuristic | 정적 사이트에 대한 자유로운 패턴 기반 추출 |
| llm | OpenRouter를 통한 AI‑지원 추출 |
| firecrawl | Firecrawl를 이용한 구조화된 추출 |
운동 경기 사이트는 일관성이 없기 때문에, 모든 경우에 적용 가능한 하나의 스크레이퍼로는 충분하지 않다. 일부 페이지는 쉽고 결정론적으로 처리해야 하며, 다른 페이지는 복잡하지만 LLM이 이해할 수 있는 형태이며, 또 다른 페이지는 JavaScript가 많이 사용되어 전혀 다른 경로가 필요하다.
메인 파이프라인
- 입력 URL을 해결합니다.
- 선택된 추출기를 구축합니다.
- 필요할 경우 HTML을 가져옵니다.
- 정규화된 코치 레코드를 출력 데이터셋에 푸시합니다.
인터페이스는 추출 전략이 아래에서 변경되더라도 안정적으로 유지됩니다.
코치당 캡처된 필드
- 이름
- 성
- 직함 또는 직위
- 이메일
- 전화번호
- 학교
- 디비전 또는 컨퍼런스
- 출처 URL
- 프로필 URL
- 이름, 이메일, 전화에 대한 신뢰도 수준
신뢰도 수준은 모든 매치가 동일하지 않기 때문에 유용합니다 (예: mailto: 링크와 본문 텍스트가 약하게 파싱된 이메일의 차이).
Heuristic Layer
휴리스틱 추출기는 빠르고, 무료이며, 명백한 패턴에 대해 신뢰할 수 있습니다. 다음 순서대로 확인합니다:
mailto:링크- Cloudflare 이메일 보호
- 사용자 정의 데이터 속성
- JavaScript 변수 패턴
- 뒤집힌 텍스트 및 간단한 난독화
- 일반 본문 텍스트
tags- 원시 HTML
스포츠 사이트는 이상한 방식을 사용합니다—하나의 페이지에 축구, 야구, 농구용 HTML과 숨겨진 모바일 레이아웃이 동시에 포함되는 경우가 많습니다. 휴리스틱 레이어는 LLM을 호출하기 전에 저수준의 쉬운 작업들을 잡아냅니다.
다중‑패스 추출
코치가 명단 페이지에 이메일 없이 표시되는 경우, 추출기는 다음을 수행할 수 있습니다:
- 코치의 프로필 URL을 따라간다.
- 프로필 모드로 추출을 다시 실행한다.
이 두 단계 접근 방식은 페이지에 걸쳐 나뉘어 있는 누락된 필드(명단 → 이름/직함, 프로필 → 소개/전화번호/이메일)를 채워줍니다.
가드레일은 잘못된 도메인을 가리키는 모델이 생성한 프로필 URL을 원본 사이트로 다시 쓰며, 허위 교차 도메인 링크가 발생하는 것을 방지합니다.
방어 기능
- SPA detection – HTML이 React/Vue/Angular 셸처럼 보이면, 휴리스틱 추출기가 빈 데이터를 반환하는 대신 명시적으로 실패합니다.
- Hidden‑content filtering – 다른 스포츠, 오래된 레이아웃, 혹은 대체 모바일 마크업에 대한 숨겨진 섹션을 제거하여 잘못된 데이터를 가져오는 것을 방지합니다.
- TLS client fingerprinting – 기본 일반 fetch 스택 대신 커스텀 fetch 레이어를 사용하여, 합성 클라이언트에 반응하는 사이트에 도움이 됩니다.
운영자 친화적 워크플로우
| Input Method | Description |
|---|---|
| Direct URL lists | 코치 페이지 URL을 포함한 일반 텍스트 또는 CSV 파일 |
| Public Google Sheets | URL 열이 있는 시트(쉽게 공유 가능) |
| Apify + Apps Script | 예약된 배치 실행을 위한 스프레드시트 기반 워크플로우 |
일반적인 사용 패턴
- 코치 페이지 URL을 Google Sheet에 입력합니다.
- 원하는 모드(휴리스틱 / LLM / Firecrawl)로 추출기를 실행합니다.
- 구조화된 코치 레코드를 가져옵니다.
반성
이 빌드는 2017년에 내가 가졌던 질문에 결국 답을 줍니다: 이 문제를 끝없는 맞춤형 스크래핑 규칙 없이도 잘 해결할 수 있을까?
- 아님 모호한 “에이전시” 마케팅 의미에서는.
- 아님 마법처럼.
- 예, 결정론적 휴리스틱과 LLM 기반 모호성 해결을 결합함으로써 지저분하고 일관성 없는 데이터를 더 잘 처리하는 방법으로.
구 버전은 휴리스틱이 모든 일을 담당했기 때문에 약 40 % 수준에 머물렀습니다. 새 버전은 휴리스틱이 명백한 부분을 처리하고, LLM이 모호한 부분을 처리하며, Firecrawl이 JavaScript‑무거운 경우를 담당하기 때문에 작동합니다.
저장소를 자유롭게 탐색하고, 추출 전략을 조정하거나, 개선 사항을 기여해 주세요!
And the pipeline follows up when the first pass is incomplete.
The next step is making that routing automatic so the system can decide, page by page, when cheap rules are enough and when a stronger extractor is worth using.