6.8 KB · 수정 2026-09-23 16:51
목차

browser-automation — 규칙·함정 (실측 정본)

지도·절차 정본 = C:\dev\tools\cdp-profiles\PORTS.md. 여긴 한 번 밟은 함정만 쌓는다.

🆕 신규

🆕 CDP 포트 사용 = 장부에 접속·완료 기록 필수 · 중복은 선착순 대기 · 마지막 사용자가 닫는다 ([페페] 26.9.23 지시)

  • 배경: 세션들이 장부 없이 같은 CDP 포트·크롬을 붙잡고 작업해 크롬이 쌓였다 → 페페가 전부 수동으로 닫음.
  • ① 포트에 붙기 전에 장부에 「접속」 기록(세션·포트·용도·시각). ② 이미 다른 세션이 쓰는 중이면 먼저 접속한 세션 우선 — 뒤 세션은 대기 순번에 올리고 기다렸다가 쓴다(끼어들기 금지).
  • ③ 끝나면 장부에 「완료」 기록. ④ 완료 시점에 대기 세션이 없으면 그 마지막 세션이 크롬을 닫는다(Browser.close 로 곱게 — 강제종료는 복원 풍선). 대기자가 있으면 닫지 않고 넘긴다.
  • 도구 = C:\dev\tools\cdp-profiles\cdplease.py — acquire <포트> "용도"(exit 3 = 대기 중, 같은 명령 다시 = 순번 유지) → 작업 → release <포트>(대기자 없으면 크롬 닫힘 · --keep = 사람이 이어 볼 때만) · status · sweep. 장부 = LEASES.json, 이력 = LEASES.log.jsonl(KST).
  • 공용 cdp.py 의 ensure()/Tab() 은 자동으로 접속·완료를 적는다(예약작업 포함, 앞사람 최대 10분 대기 = CDP_LEASE_WAIT). 직접 connect_over_cdp·chrome.exe --remote-debugging-port·curl 127.0.0.1:93xx 를 쓰면 먼저 acquire.
  • 강제 = ruleguard cdp-lease-missing(Bash 명령·실행하는 .py 본문에 CDP 포트가 있는데 이 세션이 장부에 없으면 차단). 주인이 죽으면(PID+시작시각) 다음 접속 때 자동 회수 + 대기자 없으면 크롬 닫기. 9334(페페 수동)는 자동닫기 제외.

🆕 HLS 는 hls.js 를 먼저 본다 — canPlayType('vnd.apple.mpegurl') 을 앞에 두면 크롬이 가로챈다 (2026-09-07 실측)

  • 교과서 순서(네이티브 먼저 → 없으면 hls.js)를 그대로 썼더니 윈도우 크롬이 'maybe' 를 돌려줘 네이티브 분기로 새고 hls.js 가 아예 안 만들어졌다(window._hls 가 undefined). 재생은 되는데 화질 제어권이 없어 360p 로 논다(요구는 최상 고정이었다).
  • ⛒순서를 Hls.isSupported() 먼저, 네이티브는 폴백으로 뒤집는다. 화질 고정은 MANIFEST_PARSED 에서 height(없으면 bitrate) 최대 레벨로 currentLevel 을 박으면 ABR 이 꺼진다.
  • ⚠증상만 보면 "레벨 고정 코드가 안 먹는다"로 오진한다. 판정은 window._hls 존재 여부 한 방 — 그래서 hls 인스턴스를 전역에 노출해 두는 게 싸게 먹힌다.
  • ⚠재생 중 <video> 에 키 이벤트를 붙일 땐 preventDefault 필수 — 안 하면 네이티브 컨트롤의 5초 탐색·볼륨이 겹쳐서 두 번 먹는다.
  • ⚠키 이동량을 실측할 땐 영상을 먼저 pause() 하고 재라. 재생 중이면 도구 대기시간이 그대로 오차로 들어와 +30초가 +68초로 찍힌다(실측 오진 1회).

🆕 한국 ISP SNI 차단 사이트는 NordVPN 크롬 확장 + CDP 크롬으로 뚫는다 — OS VPN 안 쓴다 (2026-09-07 실측, missav-fav)

  • 증상 = curl https://<도메인> 이 0.04초 만에 TLS RST(ConnectionResetError 10054). DNS 는 정상 응답한다. 미러 도메인이 전부 같이 막힌다(missav01.com·missav.com·missav.ws·njav.tv 실측 전부 000).
  • ⛒OS VPN 은 금지 — poin-mini 는 Tailscale·상주 서비스가 물려 있어 전체 터널이면 다 끊긴다. ⛒대신 NordVPN 크롬 확장이 깔린 프로필을 복사(copy_profile.py)해 전용 CDP 포트로 띄우고, 파이썬은 그 탭 안에서 fetch() 를 돌린다(cdp.Tab.ev(js, wait_promise=True)). 같은 오리진이라 쿠키·XSRF·Cloudflare 통과가 공짜고, 크롬 밖 네트워크는 아무 영향 없다.
  • 🔴Nord 출구를 한국으로 잡으면 안 된다 — 터널은 붙는데 사이트가 HTTP 451(법적 사유로 이용 불가) 을 준다(Nord 서울 실측). 미국(Seattle) 출구로 바꾸니 200. 페페 지시 = United States Fastest 고정.
  • 🔴프로필 복사본에 OptGuideOnDeviceModel(Gemini Nano) 이 4GB 딸려온다 — 복사 직후 지워라(347MB→265MB).
  • 웹소켓 탭 1개를 여러 스레드가 쓰면 응답이 섞인다 → threading.Lock 으로 직렬화.
  • 선례 코드 = C:\dev\tools\missav-fav\missav_fav.py(_req·_nord_connect·_get_tab), 포트 9346.

🆕 CDN 이 Referer 를 요구하고 CORS 를 안 주면 브라우저 직접재생이 불가 → 서버가 중계한다 (2026-09-07 실측)

  • 실측 = surrit.com(missav HLS 호스트)은 차단 대상이 아니라 VPN 없이 200 인데, Referer: https://missav01.com/ 가 없으면 403, 그리고 응답에 access-control-allow-origin 이 없다.
  • ⇒ 페이지에서 fetch/hls.js 로 직접 못 받는다(브라우저는 Referer 위조 불가 + CORS 차단). ⛒서버가 /hls/<uuid>/<path> 로 중계하면 끝난다 — m3u8 안이 상대경로라 재작성도 필요 없다.
  • 판정 순서를 지켜라: ①UA 만(403) ②UA+Referer(200) ③+Origin 으로 ACAO 유무 확인. 이 3방이면 5분에 갈린다.

🆕 목록 스크래퍼는 중간 페이지 1개 실패로 전체가 조용히 잘린다 (2026-09-07 실측)

  • missav-fav 가 683개짜리 저장목록을 167개(14페이지)에서 멈추고도 정상처럼 200 을 돌려줬다. 원인 = if not page_items: break — 한 페이지 실패가 곧 종료였다(메타 워커와 탭 락을 나눠 쓰다 밀렸다).
  • ⛒빈 페이지면 2초 쉬고 1회 재시도, 그래도 비면 중단 지점과 개수를 로그로 남긴다. 조용한 절단 금지.
  • 같이 밟은 것 = 로그인 여부를 문구로 판정하면 안 된다. 사이트가 클라이언트 렌더로 바뀌면 비로그인 페이지에 Log in to your account 가 아예 없어 만료를 못 잡는다 → 1페이지가 비면 만료로 본다.

🆕 재생 검증에 playwright 번들 크로미움을 쓰면 안 된다 (2026-09-07)

  • 번들 크로미움엔 H.264/AAC 독점코덱이 없다 → HLS 가 안 나오는데 코드 탓으로 오진한다. ⛒p.chromium.launch_persistent_context(..., channel="chrome") 로 진짜 크롬을 쓴다. 창은 --window-position=-32000,-32000 로 화면 밖에 park(백그라운드 규칙).
  • 자동 다음 검증은 v.currentTime = v.duration - 2 로 끝을 앞당겨 ended 를 실제로 태운다.