⚠️ 이 레포는 GitHub에서 삭제되었거나 비공개로 전환됐다 (2026-08 확인). 아래 분석은 공개 당시의 기록이다.
GITHUB 레포 딥다이브 · 2026-07-30 · FUADMEFLEH/SHARED-CLAUDE-CHATS · 5개 AI 공유링크를 마크다운으로 긁어 모으는 아카이브 + 스크래퍼

Shared-Claude-Chats 딥다이브
공유 링크 하나를 깨끗한 마크다운으로 바꾸는 5인분 스크래퍼

Shared AI Chats는 Claude·Grok·Kimi·Qwen·DeepSeek의 공개 공유 대화(public share link)를 평범한 마크다운(.md) 파일로 내려받아 모아 둔 아카이브다. 그리고 그걸 만들어 내는 여섯 개의 익스포터 스크립트가 같은 저장소에 들어 있다.

겉보기엔 "대화 모음집"이지만, 배울 게 진짜 많은 건 스크립트 쪽이다. 다섯 AI 서비스는 저마다 공유 페이지를 다르게 만든다 — 어떤 건 Cloudflare가 TLS 지문으로 봇을 막고, 어떤 건 페이지 안에 JSON을 심어 두고, 어떤 건 AWS 방화벽이 자바스크립트 퍼즐을 요구한다. 이 레포는 그 각각을 정공법으로 뚫어, 전부 똑같은 모양의 마크다운으로 뽑아낸다. 웹 스크래핑·리버스 엔지니어링·안전한 파일 쓰기의 압축 교재다.

(저장소 fuadmefleh/Shared-Claude-Chats · 언어 Python 3 · 규모 대화 1,525개 · 메시지 12,052개 · 약 33 MB · 익스포터 6개(~3,700줄) · 의존성 curl_cffi·requests 둘뿐 · TrendShift Daily 트렌딩(2026 신규))
목차
  1. 한 줄 정체
  2. 왜 주목받는가 — "공유 링크를 어떻게 긁지?"의 정답지
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 — 다섯 개의 서로 다른 관문 뚫기
  5. 디렉토리 구조 해부
  6. 학습 포인트 — 기술별 배울 것
  7. 시스템 / 실행 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 로드맵 (주차별)
  10. 핵심 키워드 사전
  11. 참고 링크

1한 줄 정체

이 프로젝트가 정확히 무엇인지 한 문장으로

Shared-Claude-Chats는 "다섯 개 AI 챗봇의 공개 공유 링크를 넣으면, 모두 동일한 형식의 깨끗한 마크다운 대화록으로 뽑아 주는 스크래퍼 모음 + 그 결과물 아카이브"다. 이름은 Claude만 들어가지만 실제로는 Claude·Grok·Kimi·Qwen·DeepSeek 5종 + 구글 AI Studio(수동)까지 6개 소스를 다룬다. 링크를 한 줄씩 텍스트 파일에 넣고 스크립트를 돌리면, 대화 한 개가 마크다운 파일 하나(제목.md)로 저장된다.

한 장의 비유

"다섯 나라 자물쇠를 다 여는 만능 열쇠 꾸러미"

같은 "대화 공유"라도 서비스마다 문 잠그는 방식이 다르다. Claude·Grok은 문지기가 손님의 걸음걸이(TLS 지문)를 보고 진짜 브라우저인지 판별하고, DeepSeek은 자바스크립트 퍼즐을 풀어야 통과시키며, Kimi는 아예 문 앞 게시판에 답을 붙여 둔다(페이지에 JSON이 박혀 있음).

이 레포는 각 문에 맞는 열쇠를 따로 깎아 만든 열쇠 꾸러미다. 그리고 어느 문으로 들어가든, 꺼내 오는 물건(마크다운 대화록)의 포장 규격은 똑같다 — 그래서 1,500개를 한 폴더에 나란히 둘 수 있다.

용어
공유 링크 / 공개 스냅샷(public share)
챗봇에서 "공유" 버튼을 누르면 만들어지는 읽기 전용 대화 사본의 URL(예: claude.ai/share/<uuid>). 로그인 없이 누구나 볼 수 있는 공개 스냅샷이다. 이 레포는 오직 이 공개 링크만 다룬다 — 비공개·삭제된 대화는 접근 불가(“not found”). 즉 인증을 우회하는 게 아니라, 이미 공개된 것을 읽는 도구다.
용어
익스포터(exporter) / 스크래퍼
웹 페이지나 API에서 데이터를 긁어와 다른 형식으로 저장하는 프로그램. 이 레포의 *_share_export.py 다섯 개가 각각 한 서비스를 담당한다. "긁는다(scrape)"고 하면 보통 HTML을 파싱하는 걸 떠올리지만, 여기선 대부분 그 페이지가 몰래 부르는 JSON API를 직접 부른다.

2왜 주목받는가 — "공유 링크를 어떻게 긁지?"의 정답지

트렌딩 이유와 비슷한 시도 대비 강점

AI 대화를 백업·인용·연구하려는 수요는 큰데, 각 서비스가 공식 내보내기(export)를 잘 안 준다. 그래서 "공유 링크를 어떻게 긁느냐"는 개발자 사이 단골 질문이다. 이 레포가 떠오른 이유는 그 질문에 대해 서비스별로 정확히 어디를 어떻게 두드리는지를, 실제로 도는 코드 + 놀랄 만큼 상세한 README로 공개했기 때문이다. 단순 도구가 아니라 리버스 엔지니어링 사례집으로 읽힌다.

두 번째 강점은 결과의 일관성이다. 6개 소스가 전부 같은 마크다운 뼈대(메타데이터 헤더 + ---로 구분된 사람/어시스턴트 턴)로 정규화된다. 그래서 이 코퍼스를 그대로 데이터셋·검색·인용에 쓸 수 있다. 세 번째는 재현성 — 링크 목록 파일이 함께 공개돼 있어 누구나 같은 아카이브를 다시 만들 수 있다.

비슷한 접근들과의 비교

항목이 레포브라우저 확장/복붙공식 데이터 내보내기
커버 범위5개 서비스 + AI Studio, 단일 규격보통 1개, 서비스별 제각각서비스마다 있거나 없음
자동화링크 목록 → 배치 실행대화마다 수동계정 전체 덤프(선택적 필터 어려움)
출력 형식깨끗한 마크다운(턴 구분·메타 헤더)HTML/서식 깨짐 흔함JSON(가공 필요)
재실행매니페스트로 이미 받은 건 건너뜀중복 관리 수동매번 전체
배울 점서비스별 관문 돌파 기법적음없음(블랙박스)
비유

다국어 통역사 팀. 다섯 명의 통역사(익스포터)가 각각 다른 언어(서비스)를 맡지만, 번역 결과는 모두 같은 표준 서식의 회의록(마크다운)으로 제출한다. 새 언어가 필요하면 통역사 한 명을 더 고용(스크립트 추가)하면 되고, 나머지는 그대로다. 서비스가 하나 바뀌어도 담당 통역사만 고치면 된다 — 관심사 분리가 코드 구조에 그대로 새겨져 있다.

균형 잡기
"공개된 것"만 — 그리고 스크린한다

스크래핑은 윤리·법적으로 민감한 영역이다. 이 레포는 두 선을 지킨다: (1) 공개 공유 링크만 접근하고 인증 우회 경로는 만들지 않으며, (2) 커밋 전에 모든 새 대화를 NSFW·개인정보(PII) 기준으로 검수해 걸리는 건 banned.txt에 넣고, 이미 올라간 건 git 히스토리까지 재작성해 지운다. 그래도 "타인의 대화를 모으는" 성격이 있으니, 학습·백업 목적으로 참고하되 무단 재배포·상업적 이용은 주의해야 한다.

3기술 스택 전체 지도

requirements.txt와 소스에서 읽어낸 실제 구성

놀랍도록 얇다. 프레임워크도, 무거운 라이브러리도 없다. requirements.txt는 딱 두 줄 — curl_cffirequests. 나머지는 전부 파이썬 표준 라이브러리(re, json, argparse, pathlib, tempfile, unicodedata, datetime)로 짰다. "의존성을 최소로, 대신 각 서비스의 실제 동작을 깊이 이해"가 이 프로젝트의 철학이다.

① 네트워킹 — 두 개의 서로 다른 HTTP 클라이언트

② 파싱 — 정규식과 json이 전부

③ 출력 & 안전장치 — 공유 헬퍼 export_io.py

용어
TLS 지문(fingerprint) / curl_cffi
브라우저가 HTTPS 연결을 열 때 주고받는 암호 협상 방식의 미세한 패턴(JA3 등)이 클라이언트마다 조금씩 다르다. Cloudflare는 이 "걸음걸이"를 보고 진짜 크롬인지, 파이썬 스크립트인지 구별한다. curl_cffi는 curl-impersonate를 감싼 라이브러리로, 크롬과 똑같은 TLS 지문을 내보내 이 검문을 통과시킨다. 헤더만 바꾸는 것과는 차원이 다른 위장이다.

4아키텍처 심화 — 다섯 개의 서로 다른 관문 뚫기

각 서비스의 공유 페이지가 어떻게 생겼고, 어떻게 데이터에 닿는가

이 레포의 진짜 내용은 "서비스 A의 공유 데이터는 정확히 어디에 있고, 그 앞에 무슨 문이 있으며, 어떻게 여느냐"를 다섯 번 반복한 것이다. 전체 파이프라인은 서비스가 달라도 모양이 같다:

┌───────────────────────────────────────────────────────────────┐ │ 링크 목록 파일 (link_lists/*.txt) # 과 빈 줄은 무시 │ │ https://claude.ai/share/<uuid> │ │ https://chat.deepseek.com/share/t119blfapmrbckthu2 ... │ └──────────────────────────────┬────────────────────────────────┘ collect_links · read_link_file ▼ ┌───────────────────────────────────────────────────────────────┐ │ extract_uuid / extract id # 추적 쿼리·로케일 제거, 순수 id만 │ └──────────────────────────────┬────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────────────┐ │ Manifest.lookup(id) → 이미 있으면 skip (─force로 강제 갱신) │ └──────────────────────────────┬────────────────────────────────┘ 없으면 ▼ fetch_snapshot(id) ← ★ 서비스별로 다름 ┌───────────────────────┴────────────────────────┐ │ Claude/Grok : curl_cffi(impersonate) → JSON API │ │ Kimi : requests → HTML 속 HYDRATION JSON │ │ Qwen : requests → 공개 JSON API(200 고정) │ │ DeepSeek : requests → WAF 밖의 data API │ │ AI Studio : 파일에서 붙여넣은 텍스트 덤프 읽기 │ └───────────────────────┬────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────────────┐ │ render_markdown() # 메타 헤더 + --- 로 구분된 사람/AI 턴 │ └──────────────────────────────┬────────────────────────────────┘ slugify · unique_path ▼ atomic_write_text ┌───────────────────────────────────────────────────────────────┐ │ claude_chats/제목.md + Manifest.record() → .json 갱신 │ └───────────────────────────────────────────────────────────────┘

① Claude · Grok — Cloudflare TLS 게이트를 지문 위장으로

두 서비스의 공유 페이지(/share/<uuid>)는 빈 SPA 껍데기다 — HTML엔 대화가 없고, 자바스크립트가 나중에 JSON API를 불러 채운다. 그래서 익스포터는 그 JSON API를 직접 호출한다(Claude는 /api/chat_snapshots/<uuid>). 문제는 그 API가 Cloudflare 뒤에 있고, Cloudflare가 헤더가 아니라 TLS 지문으로 봇을 거른다는 것. 해결책이 curl_cffi다:

# scripts/claude_share_export.py — 크롬 TLS 지문으로 위장해 호출
from curl_cffi import requests as cffi_requests
IMPERSONATE = "chrome"

response = cffi_requests.get(
    API_URL.format(uuid=uuid),
    impersonate=IMPERSONATE,                # ← 핵심: 크롬인 척
    timeout=TIMEOUT,
    headers={"Accept": "*/*", "Referer": SHARE_URL.format(uuid=uuid)},
)

흥미로운 디테일: HTTP 403이 두 가지 다른 뜻을 갖는다. Cloudflare 차단(HTML 응답)일 수도, 비공개 공유(JSON permission_error)일 수도 있다. 코드는 응답이 JSON인지 보고 둘을 구분해, "공유가 비공개다"를 "TLS 문제"로 잘못 보고하지 않는다 — 안 그러면 사용자가 애먼 curl_cffi만 업그레이드하며 헤맨다.

② Kimi — 서버가 그려 준 페이지에 JSON이 박혀 있다

Kimi는 반대다. 공유 페이지가 서버 렌더링이라 대화 JSON이 이미 HTML 안 <script>에 들어 있다. 별도 API 호출도, Cloudflare 게이트도 없어 평범한 requests로 페이지를 받아 정규식으로 상태를 뽑는다:

# scripts/kimi_share_export.py
HYDRATION_RE = re.compile(
    r"window\.HYDRATION_INIT_STATE\s*=\s*(.*?)</script>", re.DOTALL
)
match = HYDRATION_RE.search(response.text)
blob   = normalise_hydration_literals(match.group(1))   # JS 리터럴 → JSON
payload = json.loads(blob)                               # queryKey == "share" 항목에서 대화 추출

③ Qwen — 항상 200을 주는 공개 API의 함정

Qwen도 SPA 껍데기지만, API(/api/v2/chats/share/<uuid>)가 진짜 공개라 토큰 없이 열린다. 함정은 삭제·비공개 대화도 HTTP 200을 준다는 것 — 실패 신호가 상태 코드가 아니라 JSON 본문의 "success": false에 있다. 상태 코드만 믿으면 빈 대화를 "성공"으로 착각한다.

④ DeepSeek — 페이지는 못 읽지만, 데이터 API는 문 밖에 있다

가장 교육적인 사례. DeepSeek 공유 페이지는 AWS WAF의 자바스크립트 챌린지 뒤에 있다 — challenge.js를 실행 못 하는 클라이언트(curl_cffi 포함)에는 HTTP 202와 퍼즐 조각만 준다. 즉 페이지 자체는 어떤 스크립트로도 못 읽는다. 그런데 저자는 실제 브라우저로 페이지를 열고 네트워크 패널을 뒤져, 그 게이트 바깥에 있는 데이터 API를 찾아냈다:

# scripts/deepseek_share_export.py — WAF 밖의 순수 JSON API
API_URL = "https://chat.deepseek.com/api/v0/share/content"
response = requests.get(API_URL, params={"share_id": share_id}, ...)  # 토큰·쿠키 불필요

data = response.json()["data"]
if data.get("biz_code"):                                  # 200이어도 실패는 여기에
    raise ExportError(f"not found -- {data.get('biz_msg')}")
return data["biz_data"]

여기에도 함정이 둘. (1) Qwen처럼 실패가 200 안 biz_code에 숨어 있고, (2) 어떤 공유는 긴 대화의 꼬리 일부만 담겨 온다 — 가장 앞 메시지의 parent_id가 페이로드에 없는 조상을 가리켜서, 순서 복원 시 "부모가 없는 메시지를 뿌리로" 취급하는 방어 로직이 들어간다.

배울 점
"페이지를 파싱"이 아니라 "데이터의 진짜 출처를 찾기"

초보 스크래핑은 HTML을 BeautifulSoup으로 긁는다. 이 레포의 교훈은 다르다 — 화면에 보이는 것과 데이터가 오는 곳은 다르다. SPA는 대부분 뒤에서 JSON API를 부르고, 그 API가 페이지보다 훨씬 읽기 쉽고 안정적이다. 브라우저 개발자도구의 Network 패널을 열어 "이 대화는 어느 요청으로 오나"를 관찰하는 것이 스크래핑의 진짜 첫걸음이다. DeepSeek의 /api/v0/share/content는 바로 그렇게 발견됐다.

용어
SPA 껍데기 vs 서버 렌더링(SSR)
SPA(Single Page App) 껍데기: 처음 받는 HTML엔 내용이 거의 없고, 브라우저의 JS가 API를 불러 화면을 채운다(Claude·Grok·Qwen). 스크래퍼는 그 API를 직접 부르면 된다. SSR: 서버가 완성된 HTML을 주며, 데이터를 <script>하이드레이션 상태로 함께 심어 준다(Kimi). 이 경우 그 script 블록을 파싱한다.
용어
WAF 자바스크립트 챌린지
웹 방화벽(AWS WAF 등)이 봇을 거르려고 브라우저만 풀 수 있는 JS 퍼즐을 던지는 방식. 통과 못 하면 진짜 콘텐츠 대신 챌린지 스텁(DeepSeek은 HTTP 202)만 준다. TLS 지문 검문(Cloudflare)과는 다른 종류의 벽이라, curl_cffi 위장으로도 못 뚫는다 — 대신 그 벽 바깥에 있는 API를 찾는 게 정석이다.

5디렉토리 구조 해부

아카이브(결과물)와 스크립트(생성기)의 분리
Shared-Claude-Chats/ ├── scripts/ ← ★ 여섯 개의 생성기 │ ├── claude_share_export.py curl_cffi → chat_snapshots JSON API │ ├── grok_share_export.py curl_cffi → Grok 공유 JSON API │ ├── kimi_share_export.py requests → HTML 속 HYDRATION_INIT_STATE │ ├── qwen_share_export.py requests → /api/v2/chats/share (200 고정) │ ├── deepseek_share_export.py requests → /api/v0/share/content (WAF 밖) │ ├── aistudio_export.py 붙여넣은 텍스트 덤프 → 마크다운 │ └── export_io.py ★ 공유 헬퍼(atomic_write_text·resolve_within) ├── link_lists/ ← 재현용 입력: 서비스별 공유 링크 목록 │ ├── claudeaisharelinks.txt · grokaisharelinks.txt · ... │ └── qwendeploysharelinks.txt 내보내기 불가한 아티팩트 링크 격리 보관 ├── claude_chats/ (753개) + .claude-share-export.json ← 매니페스트 ├── grok_chats/ (518개) + .grok-share-export.json ├── deepseek_chats/ (171개) + .deepseek-share-export.json ├── kimi_chats/ (57개) + .kimi-share-export.json ├── qwen_chats/ (23개) + .qwen-share-export.json ├── aistudio_chats/ (3개) + .aistudio-export.json ├── raw_google_dumps/ AI Studio 원본 붙여넣기 보관소 ├── tests/test_exporter_regressions.py 회귀 테스트 ├── banned.txt ★ 검수에서 제외된 링크(재유입 방지) ├── requirements.txt curl_cffi · requests (딱 둘) └── README.md ★ 놀랍도록 상세한 1차 소스

구조가 말하는 의도는 명확하다. 왼쪽(scripts + link_lists)은 "만드는 법", 오른쪽(*_chats)은 "만들어진 것"이다. 각 *_chats/ 폴더는 결과물이면서 동시에 자기 매니페스트를 품어 스스로 "무엇을 이미 받았는지" 안다. 그래서 링크 목록에 계속 이어붙이고 다시 돌려도 안전하다(이미 있는 건 건너뜀). 파일 이름은 대화 제목에서 만들되(slugify), 비-라틴 문자(한글 등)는 그대로 둔다 — 예: 네이버-AI-모델서비스-기획-...md.

배울 점
멱등성(idempotency)을 매니페스트로 사기

좋은 배치 도구의 필수 성질: 몇 번을 돌려도 결과가 같고, 이미 한 일은 다시 안 한다. 이 레포는 폴더별 JSON 매니페스트에 "id → 저장한 파일 · 제목 · 메시지 수 · 시각"을 기록하고, 실행 초입에 lookup(id)로 확인한다. 심지어 파일을 하위 폴더로 옮겨 놔도 이름으로 알아채 다시 안 받는다. --force는 "메시지가 늘어난 대화만 다시" 받는 탈출구다. 크론으로 매일 돌리는 수집기의 교과서 패턴.

6학습 포인트 — 기술별 배울 것

이 레포를 뜯으며 실제로 손에 남는 것

1) 현대 웹 스크래핑의 진짜 첫걸음 — Network 패널 읽기

HTML을 긁기 전에 "이 데이터는 어느 요청으로 오나"를 개발자도구로 관찰하는 습관. SPA는 십중팔구 JSON API를 부르고, 그게 파싱하기 훨씬 쉽다. DeepSeek의 숨은 데이터 API를 찾은 방법이 바로 이것.

2) 안티봇 장벽의 종류와 대응 (가장 희귀)

TLS 지문 검문(Cloudflare) → curl_cffi 위장, JS 챌린지(AWS WAF) → 게이트 밖 API 찾기, 게이트 없음 → 평범한 requests. 벽마다 뚫는 방법이 다르다는 걸 실물 코드로 배운다. 이건 튜토리얼에 잘 안 나오는 실전 지식이다.

3) "성공/실패를 어디서 읽는가" — 상태 코드의 함정

Qwen·DeepSeek은 실패해도 HTTP 200을 준다. 진짜 신호는 success:false·biz_code처럼 응답 본문에 있다. API를 다룰 때 "200이면 OK"라는 순진한 가정이 왜 위험한지 체감하는 좋은 예.

4) 안전한 파일 쓰기 — 원자적 교체와 경로 방어

export_io.py 40여 줄이 보석이다. 임시파일 + fsync + os.replace로 "쓰다 죽어도 원본이 반쪽 안 남는" 원자적 쓰기, 그리고 resolve().relative_to(root)경로 탈출(디렉토리 트래버설)을 차단하는 법. 모든 파일 도구에 필요한 기본기.

5) 멱등한 배치 파이프라인 설계

매니페스트로 중복 스킵, --force로 갱신, 링크에서 순수 id 정규화, 실패 한 건이 배치를 안 죽이게 하는 예외 처리(ExportError). "밤새 돌려도 안전한" 수집기의 골격.

6) 데이터 정규화 & 출처 관리(provenance)

6개 소스를 하나의 마크다운 규격으로 통일하되, 소스별 차이(Author/Model/thinking/tool-call)를 헤더로 표현. 그리고 검수→banned.txt→히스토리 재작성으로 데이터 위생을 관리하는 실전 사례. 데이터셋을 만드는 사람이라면 반드시 볼 부분.

용어
원자적 쓰기(atomic write)
파일을 "다 쓰거나, 하나도 안 쓰거나" 둘 중 하나만 되게 하는 기법. 원본을 바로 열어 덮어쓰면 도중에 죽었을 때 반쪽 파일이 남는다. 대신 임시 파일에 완전히 쓴 뒤 os.replace로 한 번에 바꾸면, 교체는 OS가 보장하는 원자적 연산이라 항상 온전한 상태만 보인다.

7시스템 / 실행 요구사항

돌리려면 무엇이 필요한가
항목요구 / 권장
런타임Python 3(f-string·str | None 타입 힌트 사용 → 3.10+ 권장)
의존성pip install -r requirements.txtcurl_cffi(Claude·Grok)·requests(Kimi·Qwen·DeepSeek)
기본 실행python3 scripts/claude_share_export.py link_lists/claudeaisharelinks.txt -o claude_chats
입력 형태링크 파일(-f 반복 가능) 또는 바로 링크/id를 인자로. #·빈 줄 무시. -o 기본값=현재 폴더
선택 플래그--include-thinking(Claude·Qwen·DeepSeek, 추론 블록) · --include-sources(Grok, 인용 웹/X) · --force(늘어난 대화 재수집)
AI Studio공개 API 없음 → 페이지 텍스트를 raw_google_dumps/에 붙여넣고 aistudio_export.py ... --model "Gemini 2.5 Pro"
부하가벼움 — 순수 HTTP 요청 + 텍스트 처리. GPU·DB·빌드 불필요
주의
공개 스냅샷만 · 사이트 변경에 취약 · 라이선스 명시 없음

이 도구는 공개 공유 링크만 읽는다 — 비공개·삭제된 대화는 "not found"다. 그리고 각 서비스의 비공식 내부 경로에 의존하므로, 서비스가 API 경로나 하이드레이션 구조를 바꾸면 해당 익스포터가 깨질 수 있다("site may have changed" 에러). Claude 공유 API가 툴콜·검색 위젯을 This block is not supported… 자리표시자로 뭉개는 등 상류에서 이미 손실된 정보는 복구 불가다. 저장소에 LICENSE 파일이 없어(분석 시점 기준) 재사용 조건이 불명확하니, 코드·데이터를 가져다 쓸 땐 저자에게 확인하는 게 안전하다.

8직접 해볼 수 있는 실습 과제

읽기만 하지 말고 손으로 — 난이도별
LV.1 — 입문 20분

내 대화 하나를 마크다운으로 뽑기

본인 Claude 대화를 "공유"로 만들고 링크를 복사한 뒤, pip install -r requirements.txtpython3 scripts/claude_share_export.py <링크> -o out을 실행하자. out/에 생긴 마크다운을 열어 메타 헤더 + --- 턴 구분 구조를 눈으로 확인하고, --include-thinking을 켰을 때 차이를 비교하라.

LV.2 — 기초 1시간

Network 패널로 "데이터 출처" 찾기

브라우저로 Qwen이나 DeepSeek 공유 페이지를 열고 개발자도구 Network 탭을 관찰하자. 대화 내용을 담아 오는 요청(/api/...)을 찾아, 코드의 API_URL과 대조하라. "화면과 데이터의 출처는 다르다"를 직접 확인하는 훈련.

LV.3 — 중급 반나절

200-OK 함정 재현하기

Qwen/DeepSeek 익스포터에서 삭제된(또는 가짜) 공유 id를 넣어 보고, 응답이 HTTP 200인데도 success:false/biz_code로 실패를 알리는 걸 로그로 확인하라. 그런 다음 이 검사를 일부러 제거해 "빈 대화가 성공으로 저장되는" 버그를 재현했다가 되돌려, 방어 코드의 가치를 체감하라.

LV.4 — 심화 1일

여섯 번째 익스포터 만들기

다른 챗봇(예: Mistral·Perplexity 공유)을 골라, 기존 익스포터를 템플릿 삼아 <service>_share_export.py를 새로 짜자. export_io.pyatomic_write_text·매니페스트 패턴을 재사용하고, 그 서비스가 TLS 게이트·JS 챌린지·공개 API 중 무엇인지부터 Network 패널로 판별하라.

LV.5 — 도전 주말 프로젝트

수집한 코퍼스로 검색·통계 만들기

1,525개 마크다운을 파싱해 메시지 수 분포·언어·주제 통계를 내거나, 임베딩으로 시맨틱 검색을 붙여 보자. 헤더의 Source/Created/Messages를 구조화 데이터로 뽑아 작은 대시보드로 만들면, "정규화된 코퍼스"의 가치를 온몸으로 이해하게 된다.

9관련 기술 심화 로드맵 (주차별)

이 레포를 발판 삼아 스크래핑·데이터 엔지니어링으로
주차주제무엇을 / 왜
1주차HTTP & 브라우저 개발자도구요청/응답·상태 코드·헤더, Network 패널로 숨은 API 찾기. 스크래핑의 진짜 첫걸음.
2주차SPA vs SSR & 하이드레이션왜 어떤 페이지는 비었고 어떤 건 JSON이 박혀 있나. __NEXT_DATA__·하이드레이션 상태 파싱.
3주차안티봇 — TLS 지문JA3/JA4 지문, Cloudflare 검문, curl_cffi/curl-impersonate로 위장하는 원리와 한계.
4주차안티봇 — WAF & JS 챌린지AWS WAF 챌린지의 동작, "벽 밖 API 찾기" 전략, 언제 뚫지 말아야 하는지(윤리·법).
5주차견고한 API 클라이언트재시도·타임아웃·본문 기반 실패 판정(success/biz_code)·부분 응답 처리.
6주차파일시스템 안전성원자적 쓰기, fsync, 경로 탈출 방지, 유니코드 슬러그·파일명 충돌 처리.
7주차멱등한 배치 파이프라인매니페스트·체크포인트·--force·부분 실패 격리. 크론으로 매일 도는 수집기 설계.
8주차데이터 위생 & 출처 관리PII/NSFW 스크리닝, 히스토리 재작성으로 스크럽, 라이선스·재배포 윤리. 데이터셋 만드는 사람의 책임.

10핵심 키워드 사전

이 문서에 나온 용어 총정리
용어
공개 공유 스냅샷
챗봇 "공유"로 만든 읽기 전용 대화 URL. 로그인 없이 열림. 이 레포는 이것만 다룸(비공개=not found).
용어
TLS 지문 / curl_cffi
HTTPS 협상 패턴으로 클라이언트를 식별. Cloudflare가 이걸로 봇 차단. curl_cffi는 크롬 지문을 흉내 내 통과.
용어
WAF JS 챌린지
브라우저만 풀 수 있는 JS 퍼즐로 봇 차단(AWS WAF). curl_cffi로도 못 뚫음 → 게이트 밖 API를 찾음(DeepSeek).
용어
SPA 껍데기 / 하이드레이션
SPA는 빈 HTML+JS가 API로 채움(→API 직접 호출). SSR은 <script>에 데이터를 심어 줌(→정규식 파싱, Kimi).
용어
200-OK 함정
실패해도 HTTP 200을 주고 본문 success:false/biz_code로 실패를 알리는 API. 상태 코드만 믿으면 오작동.
용어
매니페스트 / 멱등성
폴더별 JSON에 "받은 대화"를 기록해 재실행 시 스킵. 몇 번 돌려도 같은 결과 → 안전한 배치.
용어
원자적 쓰기 / 경로 탈출 방지
임시파일+os.replace로 반쪽 파일 방지. resolve().relative_to(root)로 지정 폴더 밖 쓰기 차단.
용어
슬러그(slug)
대화 제목을 파일명으로 안전하게 바꾼 문자열. 비-라틴 문자는 보존, 제목 없으면 UUID로 대체.
용어
thinking / tool-call 블록
추론 모델의 사고 과정·도구 호출 로그. Claude·Qwen·DeepSeek은 --include-thinking로, Kimi는 항상 포함.
용어
출처 관리(provenance) / 스크리닝
데이터가 어디서 왔는지 기록하고, PII·NSFW를 검수해 제외(banned.txt)·히스토리 스크럽. 데이터셋 위생.

11참고 링크

더 파고들 때