1842f27d89
- 채널 인지화: news_sources.source_channel(324, documents enum 재사용) → 문서 생성 정체성(_doc_identity)·embed/chunk 30일 게이트(crawl=전량 색인)· extract 후속 override(crawl→classify, preview 스킵) 분기. - B-2 Guardian Open Platform: API 디스패치(호스트 분기, 미지 호스트=명시 실패) + show-fields=bodyText 전문 어댑터. fixture live 박제 + call-shape 테스트. - B-3 구독지: playwright-fetcher 격리 컨테이너(동시 1·요청당 브라우저·storage_state ro mount) + politeness 사람속도(30-60s) 브라우저 경로 + fulltext 인증 라우팅 (내용 기반 probe 게이트·relogin_requested 소비=open-스킵보다 앞·본문 페이월 마커 게이트) + source_health probe 컬럼(325) + 세션 박제 스크립트(맥북용). - C-2 KOSHA: 3 API live 검증·fixture 박제(board/attach/guide) — 재해사례 daily diff +첨부 PDF/HWP→extract 파이프라인, GUIDE 일일 cap 점진 백필(silent cap 금지 로그). 키는 URL 직결합(재인코딩 함정 회피). daily 06:40 KST. - C-3 정적 코퍼스: National Board 86 + TWI job-knowledge 153 일괄 CLI(멱등·politeness ·crawl_raw 보존·fulltext_worker 승격 필드 규약 동일). - C-1/C-5 시드(326): 전 URL live 검증 — UK HSE(feed-full)/안전신문/고용노동부 3종 (rss/*.do)/OSHA/EU-OSHA(후보)/SEP/1000-Word(feed-full)/Doing Philosophy/Aeon/Psyche (skip-video quirk). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.3 KiB
Python
60 lines
2.3 KiB
Python
"""B-3 구독 세션 1회 수동 박제 (MacBook 등 GUI 머신에서 실행).
|
|
|
|
르몽드 = Google OAuth — 자동화 브라우저 로그인은 Google 이 차단하므로
|
|
로그인 자체는 항상 사람이 headed 브라우저에서 수행하고, 본 스크립트는
|
|
그 결과(쿠키+localStorage = storage_state JSON)만 박제한다.
|
|
|
|
사용 (MacBook):
|
|
pip install playwright && playwright install chromium
|
|
python scripts/capture_subscription_session.py --profile lemonde --url https://www.lemonde.fr
|
|
1) 떠오른 브라우저에서 직접 로그인 (Google OAuth 포함)
|
|
2) 로그인 완료 확인 후 터미널에서 Enter
|
|
3) ~/.local/share/crawl-auth/lemonde.json 저장 (600)
|
|
|
|
GPU 반영:
|
|
ssh gpu 'mkdir -p ~/.local/share/crawl-auth && chmod 700 ~/.local/share/crawl-auth'
|
|
scp ~/.local/share/crawl-auth/lemonde.json gpu:.local/share/crawl-auth/
|
|
ssh gpu 'chmod 600 ~/.local/share/crawl-auth/lemonde.json'
|
|
|
|
세션 만료 후 재로그인도 동일 절차 + source_health.relogin_requested 플래그 set
|
|
(어댑터가 다음 틱에 half-open probe 로 소비).
|
|
|
|
주의: storage_state = credential 등가물. repo 안·백업 대상 경로에 두지 말 것.
|
|
"""
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
AUTH_DIR = Path.home() / ".local" / "share" / "crawl-auth"
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="B-3 구독 세션 storage_state 박제")
|
|
parser.add_argument("--profile", required=True, help="예: lemonde")
|
|
parser.add_argument("--url", required=True, help="로그인 시작 페이지")
|
|
args = parser.parse_args()
|
|
|
|
AUTH_DIR.mkdir(parents=True, exist_ok=True)
|
|
AUTH_DIR.chmod(0o700)
|
|
out = AUTH_DIR / f"{args.profile}.json"
|
|
|
|
with sync_playwright() as pw:
|
|
browser = pw.chromium.launch(headless=False)
|
|
context = browser.new_context(viewport={"width": 1366, "height": 900})
|
|
page = context.new_page()
|
|
page.goto(args.url)
|
|
print(f"\n브라우저에서 로그인을 완료한 뒤 이 터미널에서 Enter 를 누르세요.")
|
|
input("로그인 완료 후 Enter > ")
|
|
context.storage_state(path=str(out))
|
|
browser.close()
|
|
|
|
out.chmod(0o600)
|
|
print(f"저장: {out} (600)")
|
|
print("다음: scp 로 GPU ~/.local/share/crawl-auth/ 반영 + chmod 600")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|