2026 AI 블로그: 네이버, 티스토리, 구글, 워드프레스 자동화

AI Blog Series — 별님 자동화 프로그램 4종 통합 인덱스

https://youtu.be/4InZbKXjHlY?si=4z0clEMMXVHAWiU0

4개 플랫폼 (네이버 / 티스토리 / 구글블록 / 워드프레스) 동일 알고리즘 운영.
공통 정책 + 플랫폼별 특화 분리 구조.

최종 업데이트: 2026-05-07 22:06 (v7.1 — 보답 대상 4가지 모드 + 로테이션 자동 + 즉시 발행 + TstoryBlog 표준 폰트)


🚨 사용자 PC 필수 설정 (별님 절대 지침 v7.1 — 2026-05-07)

디스플레이 배율 = 100% 절대 유지

Windows 설정 → 시스템 → 디스플레이 → “텍스트, 앱 및 기타 항목의 크기” = 100%

배율결과
100% (필수)✅ 모든 자동화 정상 — 발행/공감/댓글/서이추 100% 성공
125%/150%⚠ 코드 자동 보정 시도 — 일부 환경에서 실패 가능
175%+❌ 권장하지 않음

별님 발견: “발행 클릭이 안 된 이유 알겠어요. 해상도 100% 가 아니면 못 찾는 것 같습니다.”

코드 측 안전망 (SetProcessDpiAwareness + devicePixelRatio 보정) 적용했으나 100% 가 가장 안전.


🌟 시리즈 구성

프로젝트플랫폼폴더 위치상태
AutoBlog네이버 블로그C:\AutoBlog\AutoBlog\✅ 1차 정리 완료 (2026-05-07)
TstoryBlog티스토리 (카카오)C:\TstoryBlog\TstoryBlog\✅ 운영 중
구글블록Google BloggerTBD⏳ 준비 중
워드프레스WordPressTBD⏳ 준비 중

📚 절대지침 구조 (B안 — 공통 + 특화 분리)

1. 시리즈 공통 (이 폴더)

C:\AI_Blog_Series\
├── README.md 👈 이 파일
├── 절대지침_공통.md ⭐ 시리즈 마스터 정책
└── 처리과정/
├── 01_황금키워드.md
├── 02_통합보답.md
├── 03_공감댓글.md
├── 04_본인답글.md
├── 05_구독_서로이웃.md
├── 06_글쓰기_이미지.md
├── 07_자격증명_로그인.md
└── 08_24시간자가점검.md

2. 각 프로젝트 (플랫폼 특화)

{ProjectRoot}/
├── README.md 👈 프로젝트 인덱스
├── 절대지침.md 👈 마스터 + 특화 안내
├── 절대지침_특화.md 👈 플랫폼 특화 (셀렉터/URL/특이사항)
└── PROGRESS.md 👈 진행 기록

⚙ 작업 시작 순서 (달님 — AI 어시스턴트)

  1. 공통 정책 읽기: 절대지침_공통.md
  2. 공통 처리 과정 파악: 작업할 모듈에 해당하는 처리과정/{번호}_*.md
  3. 플랫폼 특화 읽기: 해당 프로젝트의 절대지침_특화.md
  4. 작업 진행

✏ 정책 변경 순서 (별님 + 달님)

변경 종류수정할 파일
4개 시리즈 모두 영향C:\AI_Blog_Series\절대지침_공통.md
공통 알고리즘 변경C:\AI_Blog_Series\처리과정\{번호}_*.md
특정 플랫폼만 영향해당 프로젝트의 절대지침_특화.md
인덱스/네비게이션각 폴더의 README.md / 절대지침.md

🌟 별님 핵심 원칙 — “4개 시리즈는 한 가족”

항목통일
알고리즘시리즈 공통 (공통 마스터 + 처리과정 명시)
디자인AutoBlog GUI 마스터 기준
정책5대 감정 어조, 일일 한도, 보답 우선 등 모두 공통
사용자 경험동일 (탭 순서, 시계, 보드, 색상)

플랫폼별 차이는 셀렉터/URL 만 다름 — 각 프로젝트 절대지침_특화.md 에 명시.


📁 시리즈 공통 코드 (모든 프로젝트 동일)

다음 파일들은 4개 시리즈 모두 같은 코드 (driver 인스턴스만 외부에서 받음):

core/
├── health_report.py 🌙 자정 자가 점검 4 Phase
├── midnight_daemon.py 🌙 자정 트리거 daemon
├── gemini_client.py 🤖 Gemini API 래퍼
└── humanize.py ⏱ 사람처럼 행동 (대기 + 타이핑)
modules/
├── reply/ai_reply.py 💬 5대 감정 어조 답글
├── comment/ai_comment.py 💬 5대 감정 어조 댓글
└── comment/visitor_collector.py 👥 본인 댓글 작성자 수집 (플랫폼별 셀렉터만 다름)

🚀 새 시리즈 추가 가이드

구글블록 또는 워드프레스 추가 시:

1단계: 폴더 구조 생성

{새플랫폼}/{새플랫폼}/
├── README.md
├── 절대지침.md (마스터 + 특화 안내)
├── 절대지침_특화.md (플랫폼별 셀렉터/URL)
├── core/
└── modules/

2단계: 시리즈 공통 코드 복사

C:\AI_Blog_Series\ 의 처리과정/ 참조 → 각 모듈 구현
core/health_report.py + midnight_daemon.py + gemini_client.py 복사
modules/reply/ai_reply.py + comment/ai_comment.py 복사

3단계: 플랫폼 특화 작성

절대지침_특화.md 에:
- 로그인 흐름 (OAuth/SSO)
- 댓글 영역 셀렉터
- 좋아요/구독 버튼 셀렉터
- 글쓰기 에디터 셀렉터
- 검색 URL/API

4단계: 빌드 + 검증

pyinstaller --clean --noconfirm 빌드
[🔑 로그인 미리하기] → 자정 점검 daemon 시작 확인
각 모듈 단독 테스트

📞 연락처 / 별님 정보

  • 별님 = 사용자 (프로젝트 오너)
  • 달님 = AI 어시스턴트 (Claude / GPT / Gemini 등)

모든 작업은 별님 절대지침 우선. 절대지침과 충돌 시 별님께 먼저 확인.


📈 시리즈 진행 현황 (2026-05-06 기준)

프로젝트자정 자가 점검5대 감정 어조3단계 보답황금 키워드 100빌드
TstoryBlog✅✅✅✅✅ 17:48
AutoBlog✅✅✅✅✅ v7.1 16:20
구글블록⏳⏳⏳⏳⏳
워드프레스⏳⏳⏳⏳⏳

v7.1 추가 기능 (2026-05-06)

기능위치비고
이웃 목록 일괄 수집 (PC+모바일 / PC / 모바일 3 모드)gui/buddy_tab.pyDB 일괄 저장
서로이웃 신청 받음 일괄 수락gui/buddy_tab.pyBuddyInviteReceivedManage.naver
PC admin iframe(papermain) 자동 switchmodules/buddy/buddy_list_collector.py셀렉터 동작 보장

별님 ↔ 달님 = 좋은 동반자 🌙✨

절대지침 공통 — 4개 시리즈 통합 마스터 (별님 v7.1 — 2026-05-06)

별님 ↔ 달님 동반 정책. 4개 프로그램 (네이버 / 티스토리 / 구글블록 / 워드프레스) 동일 알고리즘 운영.

각 프로젝트 절대지침.md (개별) 는 이 마스터를 참조 + 플랫폼 특화만 추가.

정책 변경 시 반드시 이 파일을 먼저 수정 → 모든 시리즈로 동기화.

최종 업데이트: 2026-05-06 (v7.1)


📜 버전 히스토리

버전일자핵심 변경
v62026-05-05일일 한도 100 자동 추적
v72026-05-0624/7 시간 설계 + 수동값 우선 + visitor DB
v7.1 (5/6 오전)2026-05-06서로이웃 신청 일괄 수락 + 3 모드 수집 + iframe 자동 처리
v7.1 (5/6 야간)2026-05-06 23:004그래프 동기화·프리셋 충돌 해소·30자 제목·발행 다이얼로그 fix
v7.1 (5/7 오전)2026-05-07 08:00SEO 18~30자 랜덤 + 원본 제목 보존 + 엑셀 행 마지막 이동 + 동의어 dedup 제거
v7.1 (5/7 1차정리)2026-05-07 08:30popup_watcher pause + Korean 동적 + 발행 버튼 정확 매칭 — AutoBlog 1차 마무리
v7.2 (5/7 시리즈통일)2026-05-07 21:00TistoryBlog 가 AutoBlog 와 1:1 통일 — 황금 키워드 색상/파일명/폴더 + comment 5중 검사 + 시드 단독 그래프

🌐 4시리즈 1:1 통일 절대지침 (별님 v7.2 — 2026-05-07)

AutoBlog (마스터) ↔ TistoryBlog ↔ 구글블록 ↔ 워드프레스
알고리즘·디자인·파일·색상·로직 모두 동일. 차이는 오직 플랫폼별 셀렉터/URL 만.

🎨 황금 키워드 5색 티어 (모든 시리즈 동일 — 별님 절대지침)

티어검색량경쟁률배경 hex글자 hex라벨
🟡 황금≥ 500≤ 1.0#FFFF00#000000노랑
🟢 우수≥ 400≤ 2.0#00B050#FFFFFF녹색
🔵 양호≥ 300≤ 5.0#0070C0#FFFFFF파랑
🔴 도전≥ 200≤ 10.0#FF0000#FFFFFF빨강
🟤 위험≥ 100≤ 100.0#5C0000#FFFFFF검은빨강
🟣 관심(보조)≤ 200(별님 v5 정책)(보라)

적용 위치 (모든 시리즈):

  • 엑셀 PatternFill (fill_hex — # 없음)
  • GUI Treeview 행 배경 (badge_hex — # 포함)
  • GUI 하단 티어 칩 5개
  • 헤더 배경: #FFFF00 (황금 티어와 동일 — 사용자 요청)

📁 파일 정리 절대지침 (별님 v7.2 — 2026-05-09)

핵심 원칙: 한 폴더당 1000개 넘지 않기 (Windows 탐색 속도 저하 방지)
모든 시계열 파일은 년-월 폴더(YYYY-MM) 로 자동 분리.

폴더 구조 (모든 시리즈 동일):

data/
├── posts/ ← 글쓰기 마크다운
│ ├── 2026-05/ ← 월별 폴더 (자동 생성)
│ │ ├── 20260509_161432_챗GPT.md
│ │ └── ...
│ └── 2026-04/
├── images/ ← AI 생성 이미지
│ ├── 2026-05/
│ │ └── 20260509_161432_챗GPT/ ← 글당 1폴더 (그대로)
│ │ ├── 01_장점.png
│ │ └── ...
│ └── 2026-04/
├── excel/goldkeyword/
│ ├── today_gold_keyword.xlsx ← 단일 파일 (그대로)
│ └── archive/
│ └── 2026-05/ ← 월별 백업 폴더
│ └── archived_20260501.xlsx
└── health_reports/
└── {YYYY-MM-DD}.txt ← 이미 날짜 분리

자동화 규칙:

  • drafts.new_session() → posts/{YYYY-MM}/ 자동 생성
  • image_gen.generate_image() → images/{YYYY-MM}/{session}/ 자동 생성
  • 1000개 임계값 도달 시 로그 경고 출력
  • 기존 파일 마이그레이션 스크립트 1회 실행 (별님 v7.2 — 2026-05-09)

적용 대상 (모든 시리즈):

  • AutoBlog: dist/data/posts/, dist/data/images/
  • TstoryBlog: dist/data/posts/, dist/data/images/
  • 구글블록 / 워드프레스: 추후 적용

📂 황금 키워드 파일 경로 (모든 시리즈 동일)

data/
└── excel/
└── goldkeyword/ ← 단일 폴더 (시리즈 통일)
├── today_gold_keyword.xlsx ← 자동 누적 (writer 매일 자동 로드)
├── {base_keyword}_{ts}.xlsx ← 수동 검색 결과
└── archive/ ← 자동 백업

필수 함수 (core/paths.py):

  • excel_dir() — data/excel/
  • goldkeyword_excel_dir() — data/excel/goldkeyword/
  • goldkeyword_archive_dir() — data/excel/goldkeyword/archive/
  • TODAY_GOLD_FILENAME = "today_gold_keyword.xlsx"

📊 엑셀 컬럼 표준 (8 또는 10 컬럼)

AutoBlog 표준 (8컬럼): 키워드 | PC월수 | MO월수 | 총월수 | 문서수 | 경쟁률 | 발행일 | 상태

TistoryBlog v5 확장 (10컬럼): 제목 | 키워드 | PC | MO | 총 | 문서수 | 경쟁률 | 패턴 | 발행일 | 상태

엑셀 헤더 자동 감지 (3가지 layout 호환):

  • 신형 v5 final: 제목/키워드/…
  • 구형 v5 initial: 키워드/제목/…
  • legacy 8컬럼: 키워드/PC/…

💾 엑셀 저장 정책 (별님 v7.2 — 모든 시리즈 동일)

별님 핵심 명시: “AutoBlog 알고리즘 그대로, 변수까지 같이 사용”

1) 경쟁률 필터 — 0 < 경쟁률 < 100 만 저장

if r.is_published:
filtered.append(r) # 발행완료는 그대로 보존 (마지막 정렬용)
elif 0 < r.competition < 100:
filtered.append(r) # 정상 키워드
# else: 0 또는 100 이상 → 폐기 (경쟁률 = 0 = 데이터 부재, 100 이상 = 의미 없음)
케이스처리
경쟁률 = 0 (네이버 데이터 부재)❌ 폐기
0 < 경쟁률 < 100✅ 저장
경쟁률 ≥ 100❌ 폐기 (의미 없는 키워드)
경쟁률 = ∞ (검색량 0)❌ 폐기
이미 발행 완료된 행✅ 무조건 보존 (정렬상 마지막)

2) 중복 키워드 dedup — 정확 일치 (대소문자/양끝공백만 정규화)

def _canon_kw(s):
"""별님 v7.1: 정확 일치 dedup용 정규화 — 대소문자/양끝공백만."""
return str(s or "").strip().lower()

별님 절대 명시: “챗GPT / ChatGPT / chat gpt / 챗지피티” 는 모두 별개 키워드. 동의어 매핑 X (각각 SEO 가치).

3) A2 부터 데이터 — 헤더 표준화

셀내용
A1헤더 (배경 #FFFF00 노랑 + 굵게 + 가운데 정렬)
A2 ~데이터 (티어 색상 자동 적용)
freeze_panes"A2" (A1 헤더 고정)

4) 글쓰기 시 사용 — A2 첫 행을 제목으로

# writer/runner.py 흐름:
pending = excel_store.get_pending_keywords(blog_id, limit=N)
# → 발행일이 빈 행만 (미발행 큐) 반환
for row in pending:
title = row.title or row.keyword # 매력 제목 우선, 없으면 키워드
# ... AI 본문 생성 + 이미지 + 발행
excel_store.mark_published(blog_id, row.keyword)
# → 발행일 = 오늘, 상태 = "발행완료" 기록
# → sort_rows() 가 자동으로 마지막으로 이동

5) 발행 완료 → 행 마지막 이동 (자동)

def _sort_key(row):
if not row.is_published:
return (0, -row.total_volume, row.keyword) # 미발행: 검색량 큰 순서로 위
return (1, -_to_ord(row.published_at), row.keyword) # 발행완료: 최신 발행순으로 아래

→ 매번 sort_rows() 호출 시 자동으로 발행 완료된 행은 마지막으로.

6) 30일 만료 자동 부활

PUBLISH_EXPIRE_DAYS = 30
# 발행일이 30일 지난 행 → 발행일 비움 → 다음 큐로 부활
if pub_dt < (now - timedelta(days=30)):
rec["발행일"] = None
rec["상태"] = "부활"

7) Atomic Save — 사용자가 엑셀 열어둔 상태에서도 안전

1) 임시 파일 (.tmp) 에 먼저 저장
2) tmp → 본 파일 rename (atomic)
3) 잠겨있으면 2초씩 3회 재시도
4) 끝까지 실패 시 .bak.xlsx 로 백업 (다음 저장 시 합쳐서 dedup)

핵심 변수 (시리즈 공통 — 변경 X)

변수값위치
TODAY_GOLD_FILENAME"today_gold_keyword.xlsx"excel_writer.py
DAILY_MAX_KEYWORDS50excel_writer.py
PUBLISH_EXPIRE_DAYS30excel_writer.py
GOLD_MIN_SEARCH500excel_writer.py
GOLD_MAX_COMPETITION1.0excel_writer.py
GOLD_MIN_DOC1excel_writer.py
HEADER_BG"FFFF00"excel_writer.py
CUMULATIVE_CAP2000excel_store.py
EXPIRE_DAYS30excel_store.py

💬 댓글 / 답글 정책 (모든 시리즈 동일 — 별님 v7.2)

comment 모듈 — has_my_comment_already() 검사:

  • 글 진입 → 댓글 영역에서 본인 blog_id 의 댓글 검사
  • 있으면 already_my_comment 반환 → runner 가 skipped 처리
  • history.mark_processed 로 오늘 다시 X
  • 이유: “답글 없는 내 댓글 있는 글 = 모르는 분 찾기”

플랫폼별 셀렉터 (시리즈 특화 파일에 별도 명시):

  • 네이버: a.tit_name[href] / span.nick
  • 티스토리: a.tt-link-user[href] / .tt-box-meta a[href]

🤝 서로이웃 / 구독 — 5중 사전 DB 검사 (모든 시리즈 동일)

페이지 진입 전 visitor_db 5중 검사 (시간 절약 + 정확도):

#검사 함수의미반환 코드
1is_already_buddy(blog_id)이미 서로이웃/구독DB_ALREADY_BUDDY
2is_pending_request_sent(blog_id)신청 진행 중DB_PENDING_SENT
3is_decline_blocked(blog_id)영구 차단 (decline)DB_DECLINE_BLOCKED
4is_pending_buddy(blog_id)큐 대기 중 (친해진 후)DB_PENDING_BUDDY
5페이지 셀렉터 (ALREADY_*)페이지에서 직접 확인ALREADY_SUBSCRIBED 등

성공 시 자동 기록: visitor_db.upsert_visitor(blog_id, is_my_buddy=1, last_action="...") → 다음 채굴 시 자동 skip

플랫폼별 차이:

  • 네이버: 양방향 (서로이웃) — pending → accept/decline 흐름
  • 티스토리: 일방향 (구독) — pending 단계 없음, 클릭 즉시 구독

📈 자동 황금 키워드 채굴 — 시드 단독 그래프 (별님 v7.2 — 2026-05-07)

시드 진행 그래프: 메인 채굴 그래프 옆/아래에 단독 으로 표시

  • 🌐 시드 진행 (얇은 막대 + 라운드 캡 + 우측 % 사용됨)
  • 우측에 🪙 현재 시드 [N/M]: {시드명} 라벨
  • 실시간 갱신 (정규식 [N/M] 시드 'XXX' 매칭)

자동 박스 (3그래프 묶음) 폐지 — 별님 v7.2 단순화

🔄 시리즈 동기화 시 절대 변경 금지

항목모든 시리즈 동일 (변경 X)
5색 티어 색상 (5종 hex)✓ 절대 변경 X
황금 키워드 파일명 (today_gold_keyword.xlsx)✓ 절대 변경 X
엑셀 폴더 (data/excel/goldkeyword/)✓ 절대 변경 X
visitor_db 인터페이스 (is_already_buddy 등)✓ 절대 변경 X
사람 패턴 대기 시간 (humanize.py)✓ 절대 변경 X

새 시리즈 (구글블록/워드프레스) 추가 시:

  1. AutoBlog 폴더 통째 복사 → 폴더명 변경
  2. 플랫폼 특화 파일 (core/{platform}_login.py, core/{platform}_api.py, tistory_editor 같은 에디터) 만 작성
  3. 위 절대 변경 금지 항목 그대로 유지

💝 본인 블로그 공감자 목록 — 별님 라이브 셀렉터 (별님 v7.1 — 2026-05-06)

별님 라이브 검증: 본인 블로그 글의 공감자 목록 펼치기 후 추출.

펼치기 버튼

별님 # 주석셀렉터
공감자 목록 펼치기a._symList / a.btn_arr._symList / a[id^='Sympathy']
blind 텍스트“이 글에 공감한 블로거 열고 닫기”

공감자 목록 항목 (ul.list_sympathy > li.item)

추출 값셀렉터비고
컨테이너ul.list_sympathy > li.item한 명 = 1 li
블로그 linkspan.area_profile a.link.pcol2href = https://blog.naver.com/{blog_id}
블로그 제목 (title)위 link 의 title 속성예: “오니기리와 뭉치의 50억 프로젝트”
닉네임strong.nick span.ell2 a예: “오니기리와 뭉치”
블로그 설명span.desc한 줄 소개
프로필 이미지span.profile imgsrc = 썸네일 URL
⭐ 서로이웃 신청 버튼a.btn_buddy._addBuddyPopclass 에 _param({blog_id}) 포함

blog_id 추출 — _param() 패턴이 가장 정확

import re
addbtn = item.find_element(By.CSS_SELECTOR, "a.btn_buddy._addBuddyPop")
cls = addbtn.get_attribute("class") or ""
m = re.search(r"_param\(([\w_-]+)\)", cls)
if m:
blog_id = m.group(1) # 정확히 추출

공감 카운트 / 댓글 카운트 / 새 댓글 표시

정보셀렉터
공감 컨테이너div#area_sympathy{post_id}.area_sympathy
공감 카운트span.u_likeit_text._count.num
댓글 영역div.area_comment
댓글 토글a#Comi{post_id}.btn_comment
댓글 카운트em#commentCount._commentCount
새 댓글 표시i.ico_new span.icon_new (“새 댓글”)

→ 별님 답글 처리 시 “새 댓글” 표시 있는 글 우선 (정책 6 보강 가능)


🛡 서로이웃 일일 한도 — 3중 안전 메커니즘 (별님 v7.1 — 2026-05-06)

별님 결정: 시도 기반 카운트 + 90건 사전 중단 + 네이버 메시지 즉시 중단

네이버 정책: 1일 신청 시도 100건 (성공/실패 무관, skipped 제외)

3중 안전 메커니즘

#우선순위동작효과
11차 (사전)시도 90건 도달 시 사전 중단 (마진 10건)봇 의심 회피 + 안전
22차 (정확)시도 기반 카운트 (성공+실패 모두 차감)네이버와 일치
33차 (강제)“더 이상 이웃을 추가할 수 없습니다” 감지 시 즉시 중단안전장치

카운트 규칙

결과시도 카운트daily_quota 차감
✅ 신청 성공 (success)+1+1
❌ 신청 실패 (failed)+1+1
⚠ daily_limit 응답+1(즉시 중단)
⏭ skipped (이미 이웃 등)00
⏰ wait_friendship00

코드 (runner.py)

# 1차 — 사전 중단
ATTEMPTS_SAFE_MARGIN = 90
attempts_today = success + fail
if attempts_today >= ATTEMPTS_SAFE_MARGIN:
log("⚠ 안전 사전 중단 — 시도 90/100 도달")
break
# 신청 시도
result = applier.request_buddy(...)
# 3차 — 강제 중단
if result == "daily_limit":
log("🚨 일일 한도 도달")
break
# 2차 — 시도 기반 카운트
if result == "success":
daily_quota.consume(ACTIVITY_BUDDY, 1)
elif result == "failed":
daily_quota.consume(ACTIVITY_BUDDY, 1) # ⭐ 실패도 차감

🔄 서로이웃 통합 자동 동기화 — 빈도 분리 (별님 v7.1 — 2026-05-06 절대 명시)

별님 명시: “받은 신청 수락도 해주시고” — 받은 신청은 매번 즉시 처리

buddy 모듈 시작 시 자동 동기화. 빈도 분리로 효율 + 매너 동시 보장.

빈도 분리 정책

작업빈도이유
1. 받은 서로이웃 신청 일괄 수락매번 실행시간 짧음 (~5초) + 양방향 즉시 형성 + 매너 ↑
2. 이웃 목록 전체 수집 (PC+모바일)1일 1회시간 ↑ (1~2분), 5000명 이웃 가정 + 캐시 활용

영속화

flag위치의미
data/buddy_collect_YYYYMMDD.flagcore.paths.get_data_dir()오늘 이웃 수집 완료 표시
(받은 신청 수락은 flag 없음 — 매번 실행)——

흐름 (buddy/runner.py._maybe_sync_buddies_today)

[1단계 — 매번 실행]
blc.accept_all_buddy_invites(driver)
→ BuddyInviteReceivedManage.naver
→ 전체선택 + 일괄 수락
→ 자동 양방향 형성
→ 로그: "받은 신청 N명 일괄 수락"
↓
[2단계 — 1일 1회 (flag 캐시)]
flag 있으면 skip
flag 없으면:
blc.collect_all_buddies_smart(driver)
→ 모바일 우선 → PC fallback
→ 모든 이웃 (both / i_added / they_added) 수집
blc.save_to_visitor_db(entries)
→ visitor_db 채움
flag 저장 (오늘 다시 안 함)
↓
[이후 신청 흐름]
사전 DB 검증 5중 (이미 이웃, 진행 중, 거절, 대기, 안내 분류)

별님 의도 정합성

  • ✅ “받은 신청 수락도 해주시고” — 매번 즉시 수락 → 양방향 매너
  • ✅ 이웃 5000명 수집 — 1일 1회 충분 (어차피 큰 변화 없음)
  • ✅ 사전 DB 검증 정확도 ↑ — 매일 한 번 동기화로 충분
  • ✅ EXE 재시작 시 받은 신청 즉시 처리 (캐시 X)

📜 서로이웃 안내 메시지 분류 + 매너 처리 (별님 v7.1 — 2026-05-06)

별님 통찰: 상대방 신청 폼에 “조금 친해진 후에 부탁드려요” 같은 안내 메시지가 있음.
→ 무시하면 매너 ↓ + 봇 의심 ↑.

해결: 라디오 클릭 → 폼 등장 → 안내 메시지 자동 추출 → 키워드 분류 → 분기 처리.

분류 5종 (키워드 매칭 — Gemini 호출 0회)

분류키워드 예시동작
welcome환영 / 부담 없이 / 신청 받아요 / 기다리고즉시 신청
wait_friendship친해진 후 / 댓글 자주 / 방문 후 / 조금 후에오늘 X, 내일 처리 큐 등록
decline받지 않 / 거절 / 사절 / 비공개영구 skip + DB 표시
condition맞팔 / 동일 카테고리 / 비슷한 주제현재 skip + DB 메모
unknown(위 미일치)기본 신청 (무난한 인사)

흐름

[1] 라디오 클릭 (Lazy 패턴)
↓
[2] policy_reader.fetch_announce_message() — 안내 메시지 추출
↓
[3] policy_reader.classify_policy() — 키워드 분류 (Gemini 0회)
↓
[4] 분기:
welcome / unknown → 신청 진행
wait_friendship → 내일 큐 등록 (visitor_db.pending_until)
decline → 영구 skip (visitor_db.buddy_policy='decline')
condition → skip + 메모
↓
[5] (welcome / unknown 만)
AI 인사말 생성 — 안내 메시지 컨텍스트 반영 (있을 때만)
↓
[6] 입력 → 등록

다음날 큐 우선 처리 (별님 v7.1)

buddy/runner.py 시작 시:

  1. visitor_db.get_pending_buddies() — 어제 wait_friendship 등록된 큐
  2. 큐를 blog_ids 앞으로 우선 배치
  3. 자연스러운 친밀도 흐름 (어제는 안 했고 오늘 다시 시도)

영구 차단 사용자 사전 skip

  • visitor_db.is_decline_blocked(blog_id) — 페이지 진입 전 미리 체크
  • decline 정책 사용자는 페이지 진입조차 X (시간 + AI 비용 절감)

인사말 안내 컨텍스트 반영

# preview["announce_context"] 가 있으면 Gemini 프롬프트에 추가:
prompt += (
"[중요 — 상대방 안내 메시지]\n"
f"이 블로거는 신청 폼에 다음 안내를 적어두셨어요: \"{announce}\"\n"
"이 안내를 자연스럽게 존중하는 톤으로 인사말 작성. "
"매너 있게 / 부담 주지 않게 / 진심으로.\n"
)

코드 구조

파일역할
modules/buddy/policy_reader.py안내 추출 + 분류 (사전 키워드)
modules/buddy/applier.py라디오 클릭 후 정책 분기
modules/buddy/runner.py다음날 큐 우선 + decline 사전 skip
modules/buddy/ai_greeting.pyannounce_context 프롬프트 반영
core/visitor_db.pyset_buddy_policy() / get_pending_buddies() / is_decline_blocked()
(DB 컬럼)buddy_policy, pending_until

🤝 서로이웃 그룹 자동 분할 (별님 v7.1 — 2026-05-06)

별님 통찰: 네이버 이웃 한도 5,000명 / 한 그룹 1,000명 넘으면 속도 저하 + 가독성 ↓
→ 1,000명 단위로 자동 그룹 분할 + 따뜻한 그룹명

정책

항목값
네이버 이웃 한도5,000명 (서로이웃 + 일반 이웃 합산)
그룹당 인원 한도1,000명 (별님 명시)
일일 신청 한도100명 (네이버 정책)
풀 채우는 데약 50일 (5000 ÷ 100)

그룹 분할 로직

신청 시:
1) group_manager.get_appropriate_group_name()
- 마지막 사용 그룹 인원 < 1000 이면 그 그룹
- 1000 도달 시 새 그룹 자동 생성
↓
2) Selenium select 에서 일치 옵션 선택
- 일치 X 면 마지막 그룹 fallback (별님이 직접 그룹 만들어 두면 자동 사용)
↓
3) 신청 성공 시 group_manager.increment_group_count()
- 영속화: data/buddy_groups.json

그룹명 풀 (사전 정의 + AI 백업)

별님 직접 제안: 가족 같은 / 사랑하는 / 고마움을 / 좋아하는 / 동창 같은 / 마음 통함 / 이심전심

확장 (따뜻한 느낌, 20자 이내):

  • 정다운 / 응원하는 / 따뜻한 / 그리운 / 든든한 / 소중한 / 행복한
  • 햇살 같은 / 꽃 같은 / 별 같은 / 바람 같은 / 새벽 같은 / 푸른 하늘
  • 고운 인연 / 반가운 / 함께하는 / 우리들의 / 지혜로운 / 다정한 / 진실한 / 친한 벗 / 아끼는 / 기쁨 주는

→ 30개+ 사전 정의 → 30개 모두 사용 시 Gemini 호출 (백업, 비용 거의 무료)

코드 구조

파일역할
modules/buddy/group_manager.py그룹명 풀 + 인원 추적 + 영속화
modules/buddy/applier.pyselect_appropriate_group() 가 자동 분할
data/buddy_groups.json그룹별 인원 / 마지막 사용 그룹

5000명 한도 도달 시

  • runner 시작 시 group_manager.is_naver_limit_reached() 체크 → 즉시 중단
  • 로그: “🚨 네이버 이웃 한도 5000명 도달 — 더 신청 불가”

💰 AI 호출 순서 정책 — Lazy Provider (별님 v7.1 — 2026-05-06 절대 명시)

별님 통찰: “답글을 먼저 생성하였으나 신청 진행 중이거나 이미 서로이웃 팝업이 뜨면 → 작성 사라짐 → API 비용만 낭비”

해결책: 버튼 클릭 → 폼/입력창 등장 확인 → 그제야 AI 호출

잘못된 순서 (이전, v7 까지)

1) AI 텍스트 생성 (Gemini 호출 — 비용 발생) ← 비용 ↑
↓
2) 페이지 진입 → 버튼 클릭
↓
3) "이미 이웃" 팝업 → 폼 X → 작성 못 함
↓
결과: API 비용 낭비 + 봇 의심 ↑

올바른 순서 (별님 v7.1 — Lazy Provider)

1) 페이지 진입 → 신청/답글 버튼 클릭
↓
2) 폼 / 입력창 등장 확인
↓ (등장 X 면) ↓ (등장 O 면)
AI 호출 0회 (비용 ↓) AI 호출 → 텍스트 → 입력 → 등록
skipped 반환 success 반환

적용 모듈

모듈적용 여부비고
buddy/applier.py.request_buddy()✅ 필수 (별님 명시)“이미 이웃” / “신청 중” 팝업 빈번
comment/poster.py.process_single()✅ 적용입력창 없는 글 회피
reply/poster.py.post_reply()⚠ 검토 (별님: “상관없다”)본인 글이라 폼 99% 떠
integrated/runner.py✅ buddy/comment 통해 자동 적용

코드 패턴 — Callable 또는 String

# runner.py 측
def _greeting_provider():
if use_ai:
return ai_greeting.generate_for_blog(...) # 폼 떴을 때만 호출됨
return fallback_greeting
result = applier.request_buddy(driver, blog_id, _greeting_provider, log=log)
# applier.py / poster.py 측
def request_buddy(driver, blog_id, message_or_provider, ...):
# 페이지 진입 + 버튼 클릭
if not click_buddy_radio(driver):
return "skipped" # ← AI 호출 0회 (비용 절감)
# 폼 떴음 — 이제 AI 호출
if callable(message_or_provider):
message = message_or_provider() # lazy 호출
else:
message = message_or_provider # str 호환
fill_message(driver, message)
...

효과

  • API 비용 절감: 폼 안 뜨면 Gemini 호출 0회
  • 봇 의심 회피: 빈 폼에 텍스트만 남기는 것 방지
  • 호환성 유지: str 도 그대로 받음 (callable 만 lazy 처리)

🚫 모달 팝업 금지 정책 (별님 v7.1 — 2026-05-06 절대 명시)

24/7 자동화 — 모달 팝업 하나가 프로그램 정지를 유발.
별님 명시: “어떠한 곳에서도 팝업 창이 뜨지 않도록 모든 팝업 창 삭제”
유일한 예외: 사용기간 만료 알림 팝업.

금지 항목 (모든 GUI 파일)

  • messagebox.showinfo(), showwarning(), showerror() — 사용 금지
  • messagebox.askyesno(), askokcancel() — 확인 다이얼로그 사용 금지 (별님 직접 클릭 = 의도 명확)

유일한 허용

  • 라이선스 만료 / 사용 불가 알림 (app.py 의 license_check 분기)
  • 그 외 모든 알림은 self._on_status() 또는 status 라벨로 출력

대체 패턴 (코드 작성 시)

기존신규
messagebox.showerror("입력 오류", msg)self._on_status(f"[모듈] ⚠ {msg}")
messagebox.showinfo("완료", msg)self._on_status(f"[모듈] ✓ {msg}")
messagebox.showwarning("경고", msg)self._on_status(f"[모듈] ⚠ {msg}")
if not messagebox.askyesno("확인", msg): return(별님 클릭 = 의도 명확, 즉시 진행)
askyesnocancel("삭제 확인", ...)삭제 작업은 즉시 수행 (별님 명시: “삭제 해야함”)

이유:

  • 모달 팝업은 thread block — 자동화 모듈 진행 정지
  • 사용자 자리 비울 때 팝업 뜨면 → 24시간 운영 멈춤
  • 로그 출력은 비차단 + 시각적 확인 가능 + 자동화 호환

별님 v7.2 (2026-05-10 후 26) 추가 사례

별님 직접 명시: “이 프로그램은 24시간 365일 자동으로 운영 되어야 하기에
절대 팝업창이 뜨지 않아야 합니다. 단 하나 사용기간 만료, 라이선스때 팝업창 뜸”

확인된 위반 사례 (모두 제거)

  • goldkeyword_tab._clear_board() — askyesnocancel “엑셀도 삭제?” → 팝업 제거
  • schedule_dialog._apply_preset() — showinfo “프리셋 적용됨” → 로그로
  • schedule_dialog._apply_preset() — showerror “저장 실패” → 로그로
  • schedule_dialog._reset_default() — askyesno “기본 복원?” → 즉시 진행

🔁 도배 방지 + Daum 직접 요약 + 등록 검증 (별님 절대지침 — 2026-05-11 4종)

별님 직접 명시 (4가지 통합):

  1. 답글 dedup: 같은 사람에게 두 번 답글 X (도배 방지)
  2. 댓글 dedup: 내가 단 댓글에 답글 안 달렸으면 같은 사람 두 번 X
  3. 구독 시간 절약: Daum 검색 결과에서 직접 요약 추출 (글 페이지 진입 X)
  4. 등록 검증: 글 작성 끝나고 등록/확인 버튼 클릭 + 등록 완료 검증 후 다음 진행

1) 답글 dedup — 같은 사람 도배 방지

별님 증거 (2026-05-10): 같은 사람 센텀큐부동산과컴퓨터 에게 22:21, 22:23, 05:26 — 3번 답글

# modules/reply/runner.py
# 댓글 ID 단위 dedup (기존)
hist_key = f"{blog_id}/{post_no}/{comment_id}"
# ★ 같은 사람 단위 dedup (신규)
person_key = f"{blog_id}/PERSON/{author_blog_id or nickname}"
if history.is_processed_today(MODULE_NAME, person_key):
skip # "같은 분에게 오늘 이미 답글함 — 도배 방지"

2) 댓글 dedup — 내 댓글 답글 없으면 같은 사람 2번 X (기존 자동 적용)

# modules/comment/runner.py
if already_commented_without_reply(driver, own_blog_id):
skip # "내 댓글에 답글 없음 — 도배 방지"

3) 구독 시간 절약 — Daum 검색 결과에서 직접 요약

옛 (15~30초 낭비):

  • 글 페이지 진입 → 3단계 스크롤 (각 4~8초 random sleep) → 본문 추출

신 (별님 v7.2 — 2026-05-11):

  • Daum 검색 결과 페이지에서 직접 추출:
  • 셀렉터: c-doc-web > c-item-doc
  • 제목: strong.tit-g a
  • 본문 5개 슬라이드: c-contents-desc (data-swap=0~4)
  • FoundPost.summary 필드에 보관 → subscribe_blog(daum_title=, daum_summary=)
  • 페이지 진입 후 짧은 안정화만 (2~3초)
  • 약 25초 절감 / 블로그

4) 등록 검증 — 글 짤림 방지

별님 명시: “글쓰기 마치고 등록, 확인 버튼 누르고 다음 진행”

# 댓글/답글 — 등록 클릭 후
def _verify_comment_submitted(driver, textarea, max_wait_sec=4.0):
"""입력창이 비워질 때까지 폴링 — 등록 완료 검증."""
end = time.time() + max_wait_sec
while time.time() < end:
actual = driver.execute_script(
"return (arguments[0].textContent || arguments[0].value || '').trim();",
textarea,
)
if not actual or len(actual) < 3:
return True # ✓ 등록 OK
time.sleep(0.3)
# 검증 실패해도 한 템포 대기
sleep_random(1.0, 2.5)

적용 위치

모듈적용 항목
reply/runner.py✅ person_key dedup + 등록 검증
comment/runner.py✅ _verify_comment_submitted + already_commented_without_reply
subscribe/runner.py✅ daum_title/daum_summary 인자 + 15~30초 스크롤 제거
comment/post_finder.py✅ Daum 검색 결과에서 summary 추출

🔒 글쓰기 lock — 모든 보답 모듈 대기 (별님 절대지침 v7.2 후 40)

별님 직접 명시: “모든 글쓰기 통합, 공감, 서로/구독, 답글에서 글을 작성 할때에는
글쓰기가 끝나야 다음 진행 합니다. 절대지침 통합입니다.”

별님 추가 명시 (후 57): “글 쓰는 동안 기다려야함, 창을 닫는다거나, 기타 등등 X.
글 다쓰고 등록이나 확인 신청 마무리 버튼을 클릭 하였을때 다른 동작 할 수 있다.”

정책 (4 시리즈 통일)

  • core/cross_module_lock.py — byte-identical (AutoBlog / TstoryBlog / Blogger / WordPress)
  • writer/runner.py 진입 시: set_writer_active(True)
  • comment/buddy(subscribe)/reply/integrated runner 진입 시: wait_for_writer_done()
  • writer 종료 시: set_writer_active(False) (try/finally 안전 해제 — 후 42)

동작 흐름

[writer 진입]
↓ lock SET
↓ 글쓰기 진행 (Two-Phase, 이미지 paste, 발행 등)
↓ 등록/확인 마무리 버튼 클릭 + 검증
↓ lock UNSET ← 이 시점부터 다른 모듈 진행 가능

[comment/buddy/reply/integrated 시작 시도]

↓ wait_for_writer_done() — writer lock 해제 대기 (2초 poll) ↓ stop_event 시 즉시 중단 ↓ writer 종료 → 작업 재개

금지 사항 (별님 명시)

  • 글쓰기 진행 중 다른 모듈이 driver 사용 X (창 닫기/이동 X)
  • 글쓰기 끝(등록/확인 마무리 버튼) 클릭 전 절대 다른 동작 X
  • 별님 절대지침 (후 43): type_humanlike 4단계 재시도 — 글자 누락 OK, 함수 빠지지 X

💬 대화 흐름 정책 — 댓글/답글 (별님 절대지침 v7.2 후 56, 57)

별님 직접 명시:
“두번 댓글이나 답글 달지 않는다 상대가 댓글을 달았을때 가능하다,
내가 적은 댓글이나 답글에 또다시 두번 세번 반복해서 답,댓글을 달지 않는다”

1) 답글 (후 56) — 마지막 답글 작성자 검사

자식 답글 상태동작
자식 답글 없음✅ 답글 (첫 답글)
마지막 답글이 본인⏭ skip (상대 응답 대기)
마지막 답글이 상대✅ 답글 (대답글 — 대화 흐름)
# modules/reply/runner.py — comment_collector
reply_items_all = li.find_elements(
"ul.tt-list-reply li.rp_reply, "
"ul.tt-list-reply li.tt-item-reply, "
"li.rp_reply, li.tt-item-reply.rp_reply"
)
if reply_items_all:
last_reply = reply_items_all[-1]
if 마지막 답글 작성자 == 본인:
already_replied_by_me = True # skip
else:
already_replied_by_me = False # 답글 가능 (대화 흐름)

2) 댓글 (후 57) — already_commented_without_reply

내 댓글 + 답글 상태동작
내 댓글 없음✅ 댓글
내 댓글 있음 + 답글 없음⏭ skip (도배 방지)
내 댓글 있음 + 답글 있음✅ 댓글 (대화 흐름)
# modules/comment/runner.py
if already_commented_without_reply(driver, own_blog_id):
skip # "내 댓글에 답글 없음 — 도배 방지"
# else: 답글 있음 → 댓글 가능 (대화 흐름)

영구 dedup 제거 (후 57 — 후 48 정정)

  • 옛 후 48: commented_blogs 키 영구 마킹 → 너무 강함 (대화 흐름 무시)
  • 신 후 57: 시점별 검사만 사용 (already_commented_without_reply)
  • 답글도 동일 — 영구 dedup 제거 (후 56)

모듈별 적용

모듈적용 함수
comment/runner.pyalready_commented_without_reply 시점별 검사 (영구 dedup 제거)
integrated/runner.py동일 — 같은 함수 호출 (영구 dedup 제거)
reply/runner.pyhas_owner_reply 마지막 답글 작성자 검사 (후 56)

🛡 AutoBlog 보호 — 특별 지시 시만 수정 (별님 절대지침 — 2026-05-11)

별님 직접 명시: “AutoBlog 절대 특별한 지시 사항 있을때까지 프로그램은 손대지 않습니다.”

핵심 원칙

  • AutoBlog 코드 수정 절대 금지 (별님 특별 지시 시까지)
  • AutoBlog 파일 변경 절대 금지
  • AutoBlog 빌드 절대 금지
  • ✅ 읽기만 허용 — TstoryBlog/Blogger/WordPress 동기화 시 참조

4 시리즈 통일 정책 (참고용 읽기는 가능)

  • TstoryBlog 가 AutoBlog 와 통일 시 → AutoBlog 파일 읽어서 복사 (TstoryBlog 만 수정)
  • 새 시리즈 (Blogger/WordPress) 만들 때 → AutoBlog 파일 읽어서 복사

예외 (별님 명시적 요청 시만)

  • “AutoBlog 도 수정해” / “양쪽 동기화” / “4 시리즈 humanize 통일” 등 명시
  • 그 외에는 AutoBlog 절대 수정 X

별님 사례 (2026-05-10)

  • core/humanize.py 4 시리즈 통일 → 별님 “전부 통일” 명시 → 양쪽 수정 OK
  • 그 외 모든 작업 → TstoryBlog 만 수정, AutoBlog 무변경

보호 대상

C:\AutoBlog\AutoBlog\
├── core/ ✓ 읽기만
├── modules/ ✓ 읽기만
├── gui/ ✓ 읽기만
├── dist/ ✓ 읽기만
├── AutoBlog.spec ✓ 읽기만
└── data/ ✓ 별님 자산 — 절대 변경 X

📊 엑셀 헤더 표준 — A1=”키워드” 통일 (별님 절대지침 — 2026-05-11)

별님 직접 명시: “엑셀 키워드 저장시 제목열이 추가 되어 글쓰기 작동 안됨. 황금 키워드 채굴하여 저장할때 autoblog 프로그램과 동일. A2:~채굴한 키워드 삽입 저장, 글쓰기엔 A2 제목으로 발행하면 엑셀 키워드 A2는 제일 마지막 행으로 이동한다.”

핵심 원칙 (4 시리즈 통일)

  • A1 헤더 = “키워드” (AutoBlog 와 동일)
  • A2 부터 채굴된 키워드 순차 삽입
  • 글쓰기 시 A2 첫 행을 제목으로 사용
  • 발행 후 A2 행을 시트 마지막으로 이동 (다음 키워드가 A2로 올라옴)

헤더 표준 (excel_writer.COLUMNS)

COLUMNS = ["키워드", "PC월수", "MO월수", "총월수", "문서수", "경쟁률", "발행일", "상태"]

호환 헤더 (excel_input._TITLE_HEADERS)

# A1 헤더가 다음 중 어느 것이든 글쓰기 호환 (단, 표준은 "키워드")
_TITLE_HEADERS = ("제목", "title", "키워드", "keyword")

자동 정규화 (별님 v7.2 — 2026-05-11)

def ensure_default_excel_exists(path):
# 1) 파일 없음 → A1="키워드" 로 생성
# 2) 파일 있고 A1="제목" + A2 비어있음 → "키워드" 로 자동 정규화
# 3) 데이터 있는 파일은 그대로 보존 (자산 보호 절대지침)

흐름

[채굴]
A1: 키워드 | PC월수 | MO월수 | ...
A2: 챗지피티 ← 가장 우선 발행 대상
A3: 맞춤법검사기
A4: 제미나이
...
↓
[글쓰기 — A2 사용]
글 #1: '챗지피티' → 발행
↓
[발행 후 sort_rows()]
A1: 키워드 | ...
A2: 맞춤법검사기 ← A2 자리 자동으로 다음 키워드
A3: 제미나이
...
Z9: 챗지피티 (발행일 기록, 마지막으로 이동, 30일 후 부활)

절대 금지 (사용자 친화)

  • ❌ “제목” 헤더로 빈 엑셀 만들기 (글쓰기 호환 안 됨 가능성)
  • ❌ A1 헤더 변경 (4 시리즈 통일 깨짐)
  • ❌ A2 행 직접 변경 (move_row_to_last 가 자동 처리)

적용 위치

  • modules/goldkeyword/excel_writer.py — 채굴 시 저장
  • modules/writer/excel_input.py — 글쓰기 시 로드 + 자동 생성 + 정규화
  • modules/writer/excel_input.py.move_row_to_last — 발행 후 마지막 이동

📝 글쓰기 Lazy AI — 글쓰기 클릭 후 API 호출 (별님 절대지침 — 2026-05-10 후 33)

별님 직접 명시: “글 작성도 api 손실 — 글쓰기 클릭후 api 글쓰기 작성”

핵심 원칙

  • AI 본문/이미지 생성 = GoogleGemini / OpenAI Imagen API 비용 발생
  • 글쓰기 페이지 진입 실패 → AI 비용 그대로 손실 (옛 패턴)
  • check_page_ready() 가 입력란까지 다 확인 후에만 AI 호출 (Lazy 절약)

검증 단계 (writer/tistory_editor.py check_page_ready)

#검증셀렉터실패 시
1글쓰기 URL 진입https://{blog_id}.tistory.com/manage/newpostFalse (네트워크/권한 X)
2제목 입력란 발견textarea#post-title-inpFalse (페이지 로드 X)
3본문 입력란 발견마크다운 textarea#markdown-source 또는 TinyMCE iframe[id$='_ifr']False (에디터 미준비)
4모두 OK–AI 호출 진행 가능

코드 패턴 (writer/runner.py)

# ❌ 옛 — AI 먼저 호출 → 페이지 실패 시 비용 손실
post = generate_post(gemini=gemini, ...) # API 호출
write_post(driver, req) # 여기서 페이지 실패 가능
# ✅ 신 — Lazy: 페이지 입력란 다 확인 후 AI 호출
if not check_page_ready(driver, blog_id):
log("페이지 진입 실패 — AI 호출 스킵 (API 비용 절약)")
continue # 비용 0
post = generate_post(gemini=gemini, ...) # 여기서만 API 호출
write_post(driver, req) # 진입 보장된 상태

적용 범위 (4 시리즈 통일)

모듈APILazy 적용
writer/tistory_editor.check_page_readyGemini / Imagen / OpenAI✅ 페이지+제목+본문 입력란 검증 후 AI
comment/runner.write_commentGemini✅ 입력창 발견 후 provider() 호출
reply/runner.write_replyGemini✅ 입력창 발견 후 provider() 호출
subscribe/runner.subscribe_blogGemini✅ 입력창 발견 후 provider() 호출

절대 금지

  • ❌ 페이지 진입 검증 없이 AI 먼저 호출 — 비용 손실
  • ❌ 본문 입력란 미확인 상태로 본문 생성 — 마크다운/TinyMCE 모드 모를 수 있음

✍ 댓글/답글/인사 — 사람이 쓰듯이 입력 + 마무리 한 템포 (별님 절대지침 — 2026-05-10 후 32)

별님 직접 명시 (2026-05-10):

  1. “댓글 쓰다가 짤린다. 복사해서 바로 붙여 넣기도 보이는 듯 — 사람이 쓰듯이 규칙”
  2. “답글, 구독, 댓글 글자수 통일” (30~110자 — 절대지침 line 1191)
  3. “글 쓰는 시간을 정하지 말고 등록, 신청, 확인 마무리 하고 시간을 한템포 가지는 것 2~5초”

글자수 통일 (3 모듈 공통)

모듈상수MINMAX
답글REPLY_MIN/MAX30110
댓글COMMENT_MIN/MAX30110
구독 인사GREETING_MIN/MAX30110

→ 사용자가 글자수로 어느 모듈인지 구분 못하게 통일 (자연스러움 ↑)

핵심 원칙 — 입력

  • JS textContent / innerHTML 직접 설정 금지 (paste 와 동일 → 봇 감지)
  • 반드시 type_humanlike 한 글자씩 타이핑 우선 (field_type="comment")
  • 한글 IME 이슈로 입력 부족할 때만 (< 70%) JS paste fallback (마지막 수단)

핵심 원칙 — 시간 (별님 v7.2 후 32 — 정정)

  • ❌ 등록 전 대기 X — 별님 명시: “글 쓰는 시간을 정하지 말고”
  • 옛(잘못 적용): 등록 전 1.0~2.5초 대기 → 제거
  • 사람이 타이핑 끝내자마자 등록 클릭 = 자연스러움
  • ✅ 등록/신청/확인 클릭 후 한 템포 1~2.5초 — 별님 명시 (2026-05-10 후 33 정정)
  • sleep_random(1.0, 2.5, stop_event=stop_event)
  • 다음 작업으로 넘어가기 전 사람이 결과 확인하는 시간

발견된 위반 사례 (별님 v7.2 — 2026-05-10)

[22:20:41] 💬 댓글: "정쌤! GPT 이미지 프롬프트 쓸 때 늘 막막했는데..." (97자)
[22:20:43] ✅ 댓글 등록 완료 ← 2초만에 등록 = paste 의심

원인 (modules/comment/runner.py 옛 코드):

# ❌ 옛 — paste 와 동일
driver.execute_script("""
el.innerHTML = '';
el.textContent = text; // paste 효과
el.dispatchEvent(...input event...);
""", textarea, comment_text)

→ 한 번에 댓글 전체 commit → 사람 모방 X → 봇 감지 위험.

표준 패턴 (전 모듈 통일 — 별님 v7.2 후 32)

# 1차 — 사람처럼 한 글자씩 (시간 정하지 말 것 — 자연스러운 길이)
type_humanlike(
driver, textarea, comment_text,
field_type="comment", # 0.025~0.060초/글자 (참고용 — 정하지 X)
clear_first=True,
enable_pauses=True, # 10% 확률 0.5~1.2초 휴지 (생각하는 척)
stop_event=stop_event,
)
# 입력 검증 — IME 이슈로 부족하면 (< 70%) paste fallback
actual_len = len(driver.execute_script(
"return arguments[0].textContent || '';", textarea
).strip())
if actual_len < int(len(comment_text) * 0.7):
# JS paste (마지막 수단)
...
# 등록 전 = 미세 전환만 (사람이 타이핑 끝내자마자 등록)
wait_transition(stop_event=stop_event)
submit.click()
# ★ 등록 마무리 후 한 템포 (별님 절대지침 1~2.5초)
sleep_random(1.0, 2.5, stop_event=stop_event)

적용 위치 (전 모듈)

모듈함수상태
modules/comment/runner.pywrite_comment✅ 적용 (별님 v7.2 후 31)
modules/reply/runner.pywrite_reply✅ 적용 (멘션 보존 + 사람 타이핑)
modules/subscribe/runner.pysubscribe_blog✅ write_comment 재사용
modules/integrated/runner.py_process_one_visitor✅ write_comment 재사용

field_type 선택 (humanize.TIMING)

컨텍스트field_type글자당 (초)추가 휴지
댓글"comment"0.025~0.060단어 끝 + 종결부호(.!?) 뒤
답글"comment"0.025~0.060동일
인사"comment" 또는 "greeting"0.025~0.060동일
글쓰기 본문"body"0.010~0.027단어 끝
글쓰기 제목"title"0.017~0.033–

사람처럼 타이핑 시간 계산 (참고)

댓글 길이평균 타이핑 시간+ 등록 전 대기
50자약 2~3초3.5~5.5초
100자약 4.5~6초5.5~8.5초
150자약 6.5~9초7.5~11.5초

→ paste 보다 5~10배 느림 = 사람 모방 + 봇 감지 회피


📰 메인 → 첫 글 자동 이동 (별님 절대지침 — 2026-05-10 후 30)

별님 직접 명시 (HTML 셀렉터 첨부):

<strong class="title">2026년 1분기 국산차 판매 순위 TOP 6...</strong>
<p class="summary">안녕하세요!...</p>
<div class="tt-cmt" contenteditable="true">...</div>
<button class="tt_btn_subscribe" data-tiara-action-name="프로필영역 구독 버튼_클릭">

핵심: 블로그 메인 페이지(https://xxx.tistory.com/)엔 댓글 입력창과 좋아요 버튼이 없다.
→ 댓글/좋아요 모듈은 반드시 개별 글 페이지로 진입해야 동작.

발견된 문제 (별님 v7.2 사례 — 2026-05-10)

[22:00:46] [comment] ✗ @bbadam9977 댓글 실패: 댓글 입력창 없음
[22:07:01] [comment] ✗ @infogarage69 댓글 실패: 댓글 입력창 없음

원인: 포럼/visitor 풀에서 가져온 URL 이 메인 페이지(https://xxx.tistory.com/)
→ 메인엔 div.tt-cmt[contenteditable="true"] 없음 → 모든 댓글 시도 실패.

해결 패턴 (전 시리즈 적용)

def navigate_to_first_post_if_main(driver, stop_event=None) -> bool:
"""메인 페이지면 첫 번째 글로 자동 이동.
URL 패턴 `https://[blog].tistory.com/?$` → 메인.
별님 명시 셀렉터로 첫 글 링크 찾아서 driver.get(href).
"""
candidates = [
# 별님 명시 — strong.title 의 부모 a 태그
(By.XPATH, "(//a[.//strong[contains(@class,'title')]])[1]"),
# p.summary 의 컨테이너 안 a
(By.XPATH, "(//*[.//p[contains(@class,'summary')]]/a)[1]"),
# 일반 스킨 fallback
(By.CSS_SELECTOR, "article a, .article-list a, .post-item a"),
(By.CSS_SELECTOR, "a[href*='/entry/']"),
]

적용 위치 (전 시리즈)

모듈driver.get(post.url) 직후
comment/runner.py✅ 적용 (별님 v7.2 후 30)
subscribe/runner.pypost_url 사용 — 보통 글 URL 받음 (필요 시 추가)
integrated/runner.pycomment/subscribe 위임 → 자동 적용
reply/runner.py본인 글 직접 URL — 적용 불필요

표준 셀렉터 (티스토리 — 별님 v7.2 명시)

요소셀렉터
첫 글 제목strong.title (메인 페이지 글 목록)
첫 글 본문 미리보기p.summary
첫 글 링크a:has(strong.title) 또는 부모 a XPath
댓글 입력창div.tt-cmt[contenteditable="true"]
댓글 등록 버튼button.tt-btn_register:not([disabled])
구독 버튼button.tt_btn_subscribe
구독 버튼 (data-tiara)button[data-tiara-action-name="프로필영역 구독 버튼_클릭"]

절대지침 적용

  • 4 시리즈 (네이버/티스토리/구글/워드프레스) 모두 메인 → 첫 글 자동 이동 패턴 의무
  • 댓글 모듈은 메인 URL 받아도 자동 보정 (실패율 ↓)

⏱ humanize.py — 4 시리즈 통합 단일 소스 (별님 절대지침 — 2026-05-10 후 29)

별님 직접 명시: “네이버, 티스토리, 구글, 워드프레스 4개 블로그 시리즈로 프로그램 개발 중. 사람이 입력하듯 기준 기간 표 — 4개 시리즈 모두 통일”

핵심 원칙

  • 단일 소스: core/humanize.py 한 파일이 모든 모듈의 시간 정책 결정
  • 4 시리즈 동기화: AutoBlog (네이버) / TstoryBlog (티스토리) / Blogger (구글) / WordPress
  • core/humanize.py 바이트 단위 동일 (cp 로 복사 가능)
  • time.sleep() 직접 호출 금지 — 항상 humanize.* 함수 사용
  • 정책 변경 시 → 한 시리즈에서 수정 → 나머지 3개에 즉시 동기화

함수 시그니처 표준 (호환 보장)

# 모든 wait 함수: stop_event keyword-only (인터럽트 가능)
wait_transition(stage="default", *, stop_event=None) -> bool
wait_after_page_load(*, stop_event=None) -> bool
work_unit_gap(kind="default", *, stop_event=None) -> bool
smart_work_gap(kind="default", *, stop_event=None) -> bool
interruptible_sleep(seconds, stop_event=None, tick=0.2) -> bool
sleep_random(low, high, stop_event=None) -> bool
# 호환 별칭 (TstoryBlog 기존 코드 호환)
wait_inter_person, wait_inter_reply,
wait_inter_comment, wait_inter_subscribe # 모두 (*, stop_event=None)
# 타이핑 (field_type 으로 컨텍스트별 속도)
type_humanlike(driver, element, text, field_type="default", *,
clear_first=True, enable_typos=False, enable_pauses=True,
stop_event=None)
press_keys(driver, *keys)

1) TIMING dict — 글자당 타이핑 속도 (초)

field_type범위용도
id(0.03, 0.05)로그인 ID 입력
pw(0.03, 0.07)로그인 PW 입력
title(0.017, 0.033)글쓰기 제목 (1/3 단축)
body(0.010, 0.027)글쓰기 본문 (1/3 단축)
comment(0.025, 0.060)댓글 (~50ms 평균)
greeting(0.025, 0.060)인사말 (144자→9초)
keyword(0.04, 0.08)검색 키워드
default(0.04, 0.08)기타

2) TRANSITION dict — 단계 전환 (초, 별님 v7.2 ×0.67 단축)

stage범위용도
id_to_pw(0.34, 0.47)ID → PW 필드 이동
pw_to_login(0.27, 0.54)PW → 로그인 버튼
after_login(1.0, 1.7)로그인 후 페이지 안정화
after_iframe(0.34, 0.67)iframe 진입 후
title_to_body(0.4, 0.67)제목 → 본문
body_to_save(0.54, 1.0)본문 → 저장/발행
like_to_comment(0.34, 0.6)공감 → 댓글
comment_to_submit(0.4, 0.67)댓글 입력 → 등록
before_clipboard_copy(0.13, 0.27)이미지 클립보드 복사 전
between_copy_and_paste(0.20, 0.33)복사 → 붙여넣기 사이
after_image_paste(1.0, 1.67)이미지 paste 후 (단원당 ~1초 단축)
default(0.2, 0.47)기타 단계

3) WORK_UNIT_GAP dict — 작업 단위 간 (별님 v7.2 모두 2~10초 통합)

kind범위용도
comment(2.0, 10.0)댓글 → 다음 댓글
buddy(2.0, 10.0)서이추 → 다음
subscribe(2.0, 10.0)구독 → 다음 (티스토리)
writing(2.0, 10.0)글쓰기 → 다음 글
reply(2.0, 10.0)답글 → 다음 답글
person(2.0, 10.0)사람 → 다음 사람
default(2.0, 10.0)기타

4) 페이지 로드 후 안정화

상수값
PAGE_LOAD_AFTER_MIN1.0초
PAGE_LOAD_AFTER_MAX2.0초

5) 휴먼 패턴 (오타/휴지 시뮬레이션)

상수값효과
TYPO_PROBABILITY0.055% 확률 오타 → Backspace → 정타
PAUSE_PROBABILITY0.1010% 확률 글자 중간 휴지
PAUSE_RANGE(0.5, 1.2)휴지 길이
WORD_END_PAUSE(0.10, 0.30)본문 단어 끝 (공백 직전)
SENTENCE_END_PAUSE(0.20, 0.50)댓글 종결부호(.!?) 뒤
SPEED_MULTIPLIER1.0전체 배율 (<1.0 빠르게, >1.0 안전)

6) 멍때림 패턴 (비활성화 — 호환만 유지)

상수값비고
WORK_UNIT_GAP_LONG_PROB0.0비활성 (별님: “최대 2분 너무 길다”)

동기화 절차 (4 시리즈 신규 시리즈 추가 시)

# 새 시리즈 (예: BloggerBlog) 생성 시 humanize.py 즉시 복사
cp C:/AutoBlog/AutoBlog/core/humanize.py C:/BloggerBlog/BloggerBlog/core/humanize.py
# 정책 변경 시 4 시리즈 동기화 (master = 임의 시리즈)
cp C:/AutoBlog/AutoBlog/core/humanize.py C:/TstoryBlog/TstoryBlog/core/humanize.py
cp C:/AutoBlog/AutoBlog/core/humanize.py C:/BloggerBlog/BloggerBlog/core/humanize.py
cp C:/AutoBlog/AutoBlog/core/humanize.py C:/WordPressBlog/WordPressBlog/core/humanize.py

주의 (절대 금지)

  • ❌ 시리즈별로 humanize.py 다르게 유지 — 정책 분리 = 봇 감지 위험
  • ❌ 모듈 코드에서 time.sleep(N) 직접 호출 — 인터럽트 안 됨
  • ❌ stop_event 인자 누락 — 자동 모드 중지 버튼 무력화

🎯 황금 키워드 채굴 시드 정책 (별님 절대지침 — 2026-05-10 후 28)

별님 직접 명시: “시드 100개 × 시드당 100개는 깊이가 없다. 하루 100개 포스팅 하기도 힘들다 — 적게 깊게 채굴해야 한다”

핵심 원칙

  • 얕고 넓게 ❌ → 시드 많이 × 시도 적게 = 표면만 훑음, 황금 발굴 X
  • 적고 깊게 ✅ → 시드 적게 × 시도 많이 = BFS 깊이 확보, 황금 발굴 O

새 기본값 (전 시리즈 통일)

항목새 기본값범위근거
시드 개수51~200적게 — 깊이 우선
시드당 시도70010~2000깊게 — BFS 5단계까지 충분
시드당 시간20분1~605×20 = 100분 (00:30~03:00 안)

검증

  • 5시드 × 700시도 = 3500 visited / 사이클
  • 5시드 × 20분 = 100분 (1시간 40분) — 채굴 윈도우 안전
  • 분류 저장 ~50% 가정 → ~1750개 황금/우수/양호 키워드 / 사이클
  • 하루 채굴 5~10 사이클 → 자산 누적 가속

코드 위치

  • TstoryBlog: gui/goldkeyword_tab.py 라인 ~118-138 (IntVar(value=...))
  • AutoBlog: gui/keyword_tab.py 동일 위치
  • fallback 값 (.get() or N) 도 새 기본값으로 통일 필요

💎 엑셀 자산 보호 (별님 절대지침 — 2026-05-10 후 27)

별님 직접 명시: “엑셀은 지금까지 채굴한 자산입니다. 절대 프로그램 내에서 삭제 하시면 안됨”
이 프로그램은 24/365 자동 운영 → 채굴된 황금 키워드 = 누적된 자산.

핵심 원칙

  • 황금 키워드 엑셀 (today_gold_keyword.xlsx, blog별 누적 파일) = 자산
  • 프로그램 내부 어디서도 자산 엑셀 자동 삭제 금지
  • 사용자가 직접 파일 탐색기에서 삭제할 수는 있음 (그건 사용자 의도)

보드 지우기 정책 (전 시리즈 통일)

  • [🗑 지우기] 버튼 클릭 → 화면(트리뷰)만 비움
  • 엑셀 파일은 절대 보존 (자산 무손실)
  • 다음 _load_from_excel 시 다시 표시됨 → 사용자는 언제든 자산 복원 가능
  • 로그: 🗑 보드 비움 (엑셀 자산 보존 — 절대지침)

안전한 unlink (허용)

  • 임시 백업 파일 (*_BACKUP_*.xlsx, *.tmp) — 메인 자산 저장 성공 후 정리
  • 주의: 메인 파일 (today_gold_keyword.xlsx, gold_keyword_*.xlsx) 은 절대 unlink 금지

코드 점검 시 확인 항목

위치안전성
excel_writer.py bak_path.unlink()✅ 백업파일만 (메인 저장 성공 시)
excel_store.py tmp_path.unlink()✅ 임시파일만 (저장 실패 정리)
goldkeyword_tab._clear_board()✅ 화면만, 엑셀 절대 보존
신규 코드 작성 시⚠ 자산 엑셀 unlink 코드 절대 추가 금지

🌟 별님 핵심 원칙 — “4개 시리즈는 한 가족”

항목통일
알고리즘시리즈 공통
디자인AutoBlog GUI 마스터 기준
정책5대 감정 어조, 일일 한도, 보답 우선 등 모두 공통
사용자 경험동일 (탭 순서, 시계, 보드, 색상)

플랫폼별 차이는 셀렉터/URL 만 — 각 프로젝트 절대지침_특화.md 참조.


🕐 24/7 운영 시간 설계 (별님 v7 — 2026-05-06)

별님 명시: 사람이 실제 잠자는 시간 흉내 + 봇 감지 회피 + 모든 프로그램 충돌 없는 자동 분산.

일일 시간 흐름 (24시간 기준)

00:00 ~ 00:30 ⚙ 시스템 정리 (자정 자가 점검)
- 캐시/쿠키/임시파일/로그 회전
- driver 재부팅 / chromedriver 정리
- GC 강제 + 일일 한도 100 초기화
- DB 백업 (visitor / blogs / schedule)
↓
00:30 ~ 03:00 🥇 황금 키워드 채굴 (잠자는 시간 = 봇 감지 안전)
- 100개 시드 → 분석 → 5색 티어 분류
- 차단 의심 회피 (블로그/검색 엔진)
↓
03:00 ~ 04:00 🌅 자동화 프로그램 시작 (★ 랜덤 시작 ★)
- AI 패턴 회피 위해 매일 다른 시각 (3:00~4:00 사이 랜덤)
- 채굴된 황금 키워드 엑셀 → 글쓰기 시작
- 운영자 유형 4종 중 선택된 시간대 활성
↓
~ 23:59 📝 모든 자동화 모듈 운영 시간대
- 운영자 유형 (직장인/사업가/전업주부/야간부업) 별 윈도우
- 모듈 간 자동 충돌 회피
- 일일 한도 도달 시 자동 OFF
↓
00:00 (다시 자정 → 다음 사이클)

운영자 유형별 4개 프리셋 (별님 v7 표준)

유형AM 시작AM 종료PM 시작PM 종료특징
👔 직장인06:3008:3018:3022:30출퇴근 전후
🏢 사업가07:0011:0014:0023:00업무 시간 + 야근
🏠 전업주부09:0012:0013:0017:00평일 낮
🌙 야간부업(없음)—21:0025:00저녁~새벽

각 유형은 모듈별 시간대 자동 분산:

  • 황금 키워드 채굴: 00:30~03:00 (모든 유형 공통)
  • 자동화 시작: 03:00~04:00 랜덤 (모든 유형 공통)
  • 글쓰기/답글/공감/서로이웃: 유형별 윈도우 안에서 자동 분산

모듈 충돌 방지 (master_daemon)

  • 한 모듈이 driver 사용 중일 때 다른 모듈 자동 대기
  • 시간대 겹쳐도 한 번에 하나만 실행
  • 다음 사이클에서 못 한 모듈 자동 재시도

🎯 별님 절대 1순위 — “수동값 우선” 정책

별님이 GUI / 설정 파일에 명시한 값은 무조건 우선. 코드가 임의로 자동 계산/덮어쓰기 시 절대지침 위반.

우선순위 (모든 모듈 공통)

1. 1회차: 별님이 명시한 값 (수동 입력) ← 무조건 우선
↓ 1회차 끝, 2회차+
2. 2회차+: 자동 랜덤 (예약 발행 모드)
- 글쓰기 프리셋 (정보성/홈플레이트/...)
- 말투 (친근형/기본/...)
- 이미지 프리셋 (3D 랜더형/빈티지 필름/...)
- 글쓰기 간격 (30~120분 랜덤)
- 최근 3회 회피 (같은 프리셋 반복 X)
↓ 자동 랜덤 결과 없을 때
3. 코드 fallback (최후 수단)

적용 대상

설정1회차 (수동 우선)2회차+ (자동 랜덤)
글쓰기 프리셋GUI writer_preset랜덤 (최근 3회 회피)
말투GUI writer_tone랜덤
이미지 프리셋GUI image_preset랜덤
글쓰기 간격schedule.json inter_item_gap [low, high]자동 랜덤
발행 모드GUI 라디오 (즉시 발행)(1회차 그대로)
일일 한도GUI 입력값 (1~100)(남은 한도 자동 cap)

코드 패턴

# ✅ 올바른 패턴
def get_value():
user_value = config.get_manual_value() # 1순위: 사용자 명시
if user_value:
return user_value
return _auto_calculate_fallback() # 2순위: 자동 계산
# ❌ 위반 패턴 (절대지침 위반)
def get_value():
return _auto_calculate() # 사용자 설정 무시

📊 일일 한도 100 자동 추적 (별님 v6 — 2026-05-06)

활동 3종 + 통합

활동일일 한도모듈비고
buddy (서로이웃 / 구독)100subscribe/buddy + integrated 공유네이버 정책 강제
comment (공감 + 댓글)100comment + integrated 공유안전 한도 (별님 v7.1)
reply (본인 답글)♾ 무제한reply + integrated 공유별님 v7.1: 본인 글 댓글에는 네이버 한도 없음

별님 v7.1 (2026-05-06) 명시: 답글은 무제한 — 본인 블로그의 댓글에 답글 다는 것은 네이버 정책상 한도 없음.
코드: core/daily_quota.py 의 ACTIVITY_LIMITS[ACTIVITY_REPLY] = 10**9 (사실상 무제한).
입력 GUI: Spinbox to=9999, increment 10 (별님 v7.1).
처리 시 표시: (한도: 무제한 — 별님 v7.1)

동작 흐름

00:00 자정 자가 점검 → 한도 100/100/100 으로 리셋
↓
오전: 서로이웃 10개 → buddy 90 남음
오후: 통합 보답에서 50개 → buddy 40 남음 (모듈 공유)
저녁: 직접 30개 → buddy 10 남음
↓
다음날 00:00 → 다시 100/100/100

코드

from core import daily_quota
# 입력 cap
target = daily_quota.cap_input(daily_quota.ACTIVITY_BUDDY, config.target_count)
if target <= 0:
return # "오늘 한도 도달"
# 차감
if result == "success":
daily_quota.consume(daily_quota.ACTIVITY_BUDDY, 1)

🥇 황금 키워드 채굴 — 봇 감지 회피 시간대

채굴 시간 (별님 v7)

  • 00:30 ~ 03:00 (잠자는 시간 = 검색 차단 회피)
  • 시드 7개 → 1단계 → 2단계 → 3단계 (Gemini)
  • 100개 풀 → 분석 → 5색 티어 분류 → 50개 저장

5색 티어 (별님 표준)

라벨배경글자기준
🟡 황금#FFFF00검정검색≥500, 경쟁≤1.0
🟢 우수#00B050흰색검색≥400, 경쟁≤2.0
🔵 양호#0070C0흰색검색≥300, 경쟁≤5.0
🔴 도전#FF0000흰색검색≥200, 경쟁≤10
🟤 위험#5C0000흰색검색≥100, 경쟁≤100
🟣 관심#9333EA흰색검색≥500 (PC OR Mob), 경쟁≤200 — 폐기 방지

매력 제목 7대 패턴

  1. 숫자 강조 (예: “10가지 비법”)
  2. 질문형 (예: “왜 ~ 일까?”)
  3. 부정 (“~ 절대 하지 마세요”)
  4. 시급성 (“지금 안 하면 늦어요”)
  5. 비교 (“A vs B”)
  6. 비밀/노하우 (“아무도 안 알려주는”)
  7. 본인 경험 (“내가 직접 해본”)

💬 답글 / 댓글 / 인사말 — 5대 감정 어조 (시리즈 공통)

본인 답글 = 다른 분 댓글 = 구독 인사말 = 통합 보답 — 모두 동일 정책

길이 정책

  • 30~110자 (절대 준수)

5대 감정 (조합 가능)

감사 · 공감 · 소중함 · 즐거움 · 행복

필수 요소

  • 닉네임/별명 한 번 자연스럽게 호명 (OO님 ~)
  • 댓글/글 내용 자연스럽게 호응 (직접 인용 금지)
  • 이모티콘 1~3개 (31종 풀)
  • 위트 있게 작성 (별님 v7 추가)
  • 광고/홍보/외부링크 절대 금지
  • 한 단락 (줄바꿈 X)
  • 한국어 친근한 존댓말

이모티콘 풀 (31종)

🌸 🌷 🌹 💐 🌻 🌿 ☘️ 🍀 🌳 🍃 ✨ ⭐ 💫 🌟 ☀️ 🌈 ☕ 💕 💖 💗 ❤️ 🥰 😊 🤗 😄 🙌 👍 🎉 💌 ✏️ 📌

네이버 6가지 공감 반응 → 5대 감정 매핑 (별님 v7.1 라이브 발견)

네이버 글 보기 페이지의 공감 버튼은 6가지 반응 (like/impressive/thanks/haha/wow/sad).
별님 5대 감정 어조와 매핑하여 봇 패턴 회피 (한 종류만 누르지 X).

5대 감정1차 반응2차 반응data-type
감사감사공감thanks / like
공감공감칭찬like / impressive
소중함칭찬감사impressive / thanks
즐거움웃김공감haha / like
행복공감칭찬like / impressive

분산 정책 (별님 v7 — 봇 감지 회피):

  • 공감(like) 60% + 나머지 5종 골고루 40%
  • 한 종류 연속 클릭 X (최근 3회 회피)
  • 슬픔(sad)은 신중 사용 (글 내용 부정적일 때만)

셀렉터:

  • 공감 토글: a.u_likeit_button._face
  • 6 반응 layer: ul.u_likeit_layer._faceLayer
  • 개별 반응: li.u_likeit_list.{like|impressive|thanks|haha|wow|sad} a._button

전체 셀렉터 표는 처리과정/03_공감댓글.md 의 D 섹션 참조.

모바일 글 보기 — #_post_property 메타 div ⭐ (별님 v7.1 핵심 발견)

모바일 페이지 (m.blog.naver.com/{blog_id}/{post_id}) 의 숨겨진 div 한 곳에 모든 메타 정보.
PC 페이지에서 여러 element 추출보다 ~5배 빠른 메타 획득.

prop = driver.find_element(By.CSS_SELECTOR, "div#_post_property")
relation = prop.get_attribute("relationtypewithblog") # 0/1/2/3 — 이웃 관계
comment_enabled = prop.get_attribute("commentenable") == "true"
is_blacklist = prop.get_attribute("isblacklistuser") == "true"
comment_count = int(prop.get_attribute("commentcount") or 0)
add_date_ms = int(prop.get_attribute("adddate") or 0)

자동화 활용:

  • relationtypewithblog → 이미 서로이웃이면 신청 skip (= "1" 체크)
  • commentenable="false" → 댓글 모듈 즉시 skip
  • isblacklistuser="true" → 차단 사용자, 모든 처리 skip
  • commentcount → 빈 글 (0) skip / 활발한 글 (10+) 우선

권장: 모바일에서 메타 빠른 추출 → PC 로 전환해 댓글 작성 (각 모드 강점 활용).
전체 모바일 셀렉터 표는 처리과정/03_공감댓글.md 의 M 섹션 참조.


↩ 본인 답글 모듈 (별님 v7.1 — 무제한 한도 확정)

일일 한도 — ♾ 무제한 (별님 v7.1 절대 명시)

  • 본인 블로그 댓글에 답글 다는 것은 네이버 정책상 한도 없음
  • 코드: daily_quota.ACTIVITY_LIMITS[ACTIVITY_REPLY] = 10**9 (사실상 무제한)
  • GUI: Spinbox to=9999, increment=10
  • runner: TARGET_HARD_LIMIT = 10**9 (cap 없음)
  • 로그 표시: 한도: 무제한 — 별님 v7.1

글 분석 범위 — ♾ 무제한 (별님 v7.1 — 2026-05-06)

  • 첫 실행 100개 / 2회+ 20개 → 첫 실행 무제한 / 2회+ 무제한 (전부 분석)
  • RSS / HTML이 주는 모든 본인 글 분석
  • 코드: max_posts = 9999 (사실상 무제한)
  • 시간 단축은 정책 6 (News.naver) + 정책 4 (모바일 사전 필터) 로 자동 처리
  • 공감/댓글 작성자의 ID/별명/내용/날짜 → DB 화 (data/comment_visitors_{blog_id}.json)

처리 정책 — 끝까지 진행 (별님 v7.1)

  • 답글 작성 안 한 새 댓글만 처리
  • 입력값(1~9999) 만큼

종료 조건 — 다음 중 하나라도 발생 시 종료 (별님 v7.1 — 2026-05-06)

#조건동작
A답글 성공 카운트 = 입력값 도달✅ 목표 달성 → 즉시 종료
B본인 글 풀 완전 소진 (더 이상 분석할 글 없음)📭 종료
Cstop_event 발생 (사용자 정지)⏹ 즉시 중단
D자동 스케줄 시간 윈도우 종료⏰ 즉시 중단
E일일 한도 메시지 감지 (현재는 무제한이지만 안전장치)🚨 즉시 중단
F연속 실패 3회 (네이버 차단 의심 안전장치)⚠ 즉시 중단

별님 명시: “100을 입력 하였다면 100개가 작성될 때까지, 블로그 글이 더 이상 존재하지 않을 때까지, 프로그램 진행 시간이 끝날 때까지 계속 진행 함.”

즉 — 새 댓글 부족이라도 글 풀이 남아 있으면 더 옛날 글까지 거슬러 올라가서 분석 (페이지네이션).

보드 실시간 동기화 (별님 v7.1 — 2026-05-06)

  • runner.py 가 처리 시 core.visitor_board.add_event() 호출
  • 답글 OK ✅ / 이미답글 ⏭ / 오늘처리 ⏭ / 실패 ❌ 모두 보드에 즉시 반영
  • GUI 보드 위젯이 1.5초마다 polling → 화면 갱신

5대 감정 어조 + 위트 + 110자

빠르게 실행 — 6가지 정책 (별님 절대지침 / TistoryBlog 표준 + v7.1)

시간 80% 단축 — 50개 글 중 3~5개만 실제 진입.
별님 v7.1 (2026-05-06): 5번째 관리자 이웃관리 DB 매칭 + 6번째 내소식 페이지 직접 활용.

#정책플랫폼
1댓글 ≥ 1 인 글만 필터링시리즈 공통
2사이드바 최근 댓글 우선 (div.recent-comment)티스토리
3빠른 댓글 수 체크 (em#commentCount)네이버
4모바일 글 목록 사전 필터 (span.comments__iipHc)네이버
5 ⭐관리자 이웃관리 DB 매칭 + 신청 일괄 수락네이버
6 ⭐⭐내소식 페이지 직접 활용 (m.blog.naver.com/News.naver) ★최고속★네이버

6번 정책 핵심 (별님 v7.1 — 가장 빠른 처리)

https://m.blog.naver.com/News.naver = 본인이 받은 모든 알림 한 페이지에 누적:

  • 새 댓글 / 공감 / 이웃 신청 / 멘션 알림 모두

→ 본인 글 50개 순회 X → 단 한 페이지로 즉시 처리 → 글로 직접 점프해 답글 작성.

본인 정보 자동 추출 (별님 라이브 발견)

정보셀렉터
본인 닉네임div.nickname__rkKeV
본인 blog_iddiv.blog_id__eKHcP span.text__jvRR4
오늘/전체 방문자em.stats_count

→ credential_loader 없이도 즉시 확보.

처리 속도 비교

정책답글 1개당 시간
정책 0 (단순 50글 순회)~30초
정책 1+3+4 (v7)~8초
정책 1+3+4+5 (v7.1 DB 매칭)~5초
정책 6 단독 (내소식 활용) ⭐⭐~2~3초
정책 5+6 통합 최적 ⭐⭐⭐~1~2초

전체 셀렉터 / 코드 위치는 처리과정/04_본인답글.md 의 “빠르게 실행 6가지” 섹션 참조.


🤝 서로 이웃 / 구독 모듈 (별님 v7 명시)

DB 우선 활용

  • 본인 답글 모듈이 저장한 DB 사용
  • DB 의 visitor → 서로이웃 / 구독 신청
  • 메시지 위트 있게 작성

DB 부족 시 보충

  • 새 키워드로 블로그 검색
  • 입력값(설정) 충족까지 신규 추가
  • 하루 최대 100개 (네이버 정책 / 티스토리 안전선)

종료 조건

  • 입력값 충족 → 즉시 종료
  • 또는 일일 한도 100 도달

💬 공감 / 댓글 모듈 (별님 v7 명시)

DB 우선 활용

  • 답글 모듈 DB → 공감/댓글
  • 위트 있게 작성

DB 부족 시 보충

  • 새 키워드로 블로그 검색
  • 입력값(설정) 충족까지 신규 추가
  • 하루 최대 200개 ~ 무한 (별님 v7)

종료 조건

  • 입력값 충족
  • 또는 일일 한도 도달

🤝 통합 보답 모듈 (별님 v7 명시)

실행 순서 (별님 명시)

1. 본인 답글 (DB 생성/갱신)
↓
2. 서로 이웃 (DB 활용 → 부족 시 키워드 검색)
↓
3. 공감 / 댓글 (DB 활용 → 부족 시 키워드 검색)

충돌 방지

  • 통합 보답 vs 개별 모듈 (답글/서이추/공감) — 동시 실행 X
  • 한 사람당 답글+좋아요+댓글+서이추 모두 처리하는 통합 vs 단독 운영
  • master_daemon 이 락 관리
  • 서로 다른 3개 모듈 — 동시 실행 가능
  • 예: 답글 (모듈 A) + 서이추 (모듈 B) + 공감/댓글 (모듈 C) 동시 OK
  • 단, 각 모듈은 별도 driver 슬롯 사용

친밀도 우선 (수집)

순위대상효과
1차본인 답글 DB visitor친밀도 ↑
2차본인 블로그 구독자/이웃기존 인연
3차키워드 검색새 발견 (구독 X)
4차본인이 구독한 블로그양방향

✍ 글쓰기 모듈 — 3개 구성 (별님 v7 명시)

구성

1. 글쓰기 프로그램 (본문 생성 + 프리셋/말투/구조)
2. 이미지 생성 프로그램 (본문 ### 마다 이미지)
3. 네이버/티스토리/... 글쓰기 프로그램 (에디터 자동 입력 + 발행)

“수동값 우선” 정책 (별님 v7 절대 적용)

글쓰기 프로그램

  • 1회차: 별님 GUI 입력값 우선 (정보성/친근형/…)
  • 2회차+: 예약 발행 자동 랜덤
  • 프리셋 랜덤 (최근 3회 회피)
  • 말투 랜덤
  • 본문 ###/구조 랜덤

이미지 프로그램

  • 1회차: 별님 GUI 입력값 우선 (3D 랜더형/…)
  • 2회차+: 자동 랜덤 (최근 3회 회피)

네이버 글쓰기 프로그램

  • 1회차: 별님 GUI 입력값 우선
  • 2회차+: 예약 발행 자동 랜덤
  • 글쓰기 간격 30~120분 진짜 랜덤
  • 발행 모드 (즉시 발행 / 임시저장 등)

글자 수

  • 9 프리셋: 9문단, ≈ 1,500자
  • 14 프리셋: 14문단, ≈ 2,500자 (기본)
  • 22 프리셋: 22문단, ≈ 4,000자

네이버 SmartEditor 3 — PC 글쓰기 핵심 셀렉터 (별님 v7.1 라이브 검증)

전체 셀렉터 표는 처리과정/06_글쓰기_이미지.md 의 SmartEditor 3 섹션 참조.

영역핵심 셀렉터비고
에디터 본체div.se-body.__se-bodydata-theme="greenLight" / lang="ko-KR"
제목 컴포넌트div.se-component.se-documentTitledata-a11y-title="제목"
본문 컴포넌트div.se-component.se-textdata-a11y-title="본문"
입력 단락p.se-text-paragraphline-height 1.6
텍스트 노드span.se-ff-nanumgothic.se-fs19.__se-node19pt 본문
본문 placeholder“글감과 함께 나의 일상을 기록해보세요!”사라지면 입력 확정
사진 삽입 (툴바)button[data-name='image']data-log: dot.img
내돈내산 ⭐button[data-name='not-sponsored-button']별님 v7.1 신규 — 광고 글 식별 회피

PC UA 필수 (mobile_ua=False) — 모바일 글쓰기는 다른 구조.


🌙 24시간 자가 점검 — 자정 정각 + 30분 (별님 v7)

트리거 — A 방식 (내장 daemon thread)

  • 모듈: core/midnight_daemon.py
  • 윈도우: 00:00 ~ 00:30 (별님 v7 — 30분 충분 시간)
  • 매분 시간 체크 → 00:00 진입 시 자동 실행
  • 하루 한 번 보장

5단계 자가 점검

Phase동작모듈
1. 로그 분석ERROR/WARN, 모듈별 실패율, 의심 패턴health_report.analyze_logs
2. 리소스 점검RAM, chrome 프로세스, 임시 dirhealth_report.check_resources
3. 백업 + 회전DB/설정 백업, 10MB+ 로그 gzip, 7일+ 정리health_report.backup_and_rotate
4. driver 정리(영속) quit + 새 / (driver_session) 잔존 정리 + GChealth_report.restart_driver
5. 일일 한도 초기화모든 활동 100 으로 리셋daily_quota.reset_all()

종합 상태 판정

  • ok: ERROR ≤ 30, RAM < 1.5GB
  • warn: ERROR 30~100, 의심 패턴 1+
  • critical: ERROR 100+, 의심 패턴 3+

리포트

  • data/health_reports/{YYYY-MM-DD}.txt — 한국어 요약
  • data/health_reports/{YYYY-MM-DD}.json — 분석용
  • 다음날 시작 시 GUI 로그에 어제 점검 한 줄 표시

🎨 시리즈 디자인 통일 (AutoBlog GUI 마스터 기준)

색상 팔레트 (styles.py SERIES_* — 절대 변경 X)

의도hex변수
성공 / OK#16a34aSERIES_GREEN
실패 / 정지#dc2626SERIES_RED
정보 / 진행#0369a1SERIES_BLUE
경고 / 한도#f59e0bSERIES_AMBER
비활성#9ca3afSERIES_GRAY
황금 / 강조#fbbf24SERIES_GOLD
어두운 배경#0f172aSERIES_DARK_BG

시계 위젯 (시리즈 통일)

  • 배경 #0f172a (절대 변경 X)
  • 시침 #fbbf24 황금 (24h)
  • 분침 #e2e8f0 흰색 (60m)
  • AM 호 #D4A017 황금 / PM 호 #1E40AF 파랑
  • 상태 #22c55e 녹색
  • 어휘: ▶ 실행중 / 📍 동작중 / ⏰ 대기중 / 💤 휴식중 / ⏸ 비활성
  • 순서: 황금 → 통합 → 공감 → 구독 → 답글 → 글쓰기

노트북 탭 라벨 (순서 통일)

자격증명 → 황금 키워드 → 통합 보답 → 공감/댓글 → (서로이웃|구독) → 본인 답글 → 글쓰기

통합 시간 설정 다이얼로그 — 4프리셋 + 자동 랜덤 (별님 v7.1)

  • 👔 직장인 / 🏢 사업가 / 🏠 전업주부 / 🌙 야간부업
  • 시간 ±버튼: ▲▼ (한 번 클릭에 ±10분) — 별님 v7.1 (TistoryBlog 패턴 통일)
  • 간격 ±버튼: ▲▼ (한 번 클릭에 ±10분) — 별님 v7.1
  • 가로 너비: 980px (이전 1280 → 컴팩트)

🎲 자동 랜덤 시간 설정 (별님 v7.1 — 매일 3~4시 자동)

  • 토글 ON 시: 매일 03:00~04:00 사이 랜덤 시각에 4 프리셋 중 무작위 1개 자동 적용
  • 봇 패턴 회피 ↑ — 매일 다른 시각 + 매일 다른 프리셋 (같은 프리셋 연속 회피)
  • 저장: data/auto_preset.json (enabled / today_apply_at / today_applied)
  • 자정 자가 점검 Phase 7: 새 날 적용 시각 재결정
  • master_daemon: 매분 체크 → auto_preset.maybe_auto_apply()
  • “지금 즉시 무작위 적용” 버튼: 별님이 수동으로 즉시 무작위 적용 가능
  • 코드: core/auto_preset.py

👥 visitor DB 시스템 (별님 v7 — 2026-05-06)

별님 명시: 답글/공감/댓글/서이추 모든 모듈이 같은 DB 활용. 외부 + 내부 양 방향 수집.

카테고리 (별님 v7)

분류정의
신청자별님이 서이추 신청한 사람
신청해야본인 글에 댓글/공감 줬는데 서로이웃 X
공감자본인 글에 공감 한 사람
공감해야별님이 그 사람 글에 공감 안 한 사람
댓글자본인 글에 댓글 단 사람
댓글해야별님이 그 사람 글에 댓글 안 한 사람

관계 (네이버 이웃 관리)

관계의미
both서로이웃 (양방향)
i_added내가 추가만 (상대 X)
they_added상대만 나를 추가
none무관계 (검색 발견)

우선순위 (친밀도)

순위대상분류
1차본인 글 댓글/공감자close
2차서로이웃buddy
3차나를 추가만follower
4차키워드 검색 신규new

외부 수집 (한 번에 대량) — 별님 v7.1 (2026-05-06)

모듈: modules/buddy/buddy_list_collector.py

3 모드 GUI (별님 v7.1 — 별도 메뉴 제공)

모드함수설명
🌐 PC + 모바일 (자동)collect_all_buddies_smart()모바일 우선 → 실패 시 PC fallback
🖥 PC 전용collect_all_buddies_pc()admin.blog.naver.com (4 필터 모두 순회)
📱 모바일 전용collect_all_buddies()m.blog.naver.com (탭 2종)

페이지별 정보

PC admin (iframe 내부 — 별님 v7.1 핵심 발견)

https://admin.blog.naver.com/BuddyMeManage.naver (나를 추가한 이웃)
https://admin.blog.naver.com/BuddyListManage.naver (내가 추가한 이웃)
https://admin.blog.naver.com/BuddyInviteReceivedManage.naver (서로이웃 신청 받음)
  • ⚠ 중요: admin 페이지는 <iframe id="papermain"> 내부 렌더링 — 셀렉터 진입 전 반드시 driver.switch_to.frame() 필요
  • helper: _switch_to_papermain_iframe() (최대 6초 대기 → switch → 종료 시 default_content 복귀)

PC 4 필터 드롭다운

필터셀렉터의미
전체span.sel_tp나를 이웃으로 추가한 사람 전체
서로이웃span.sel_tp2양방향
내가 추가만span.sel_tp3나도 이웃으로 추가한 사람
상대만 추가span.sel_tp4상대만 나를 추가한 사람

PC 행 구조

<td class="buddy">
<span class="nickname">행정솔루션즈</span>
<a href="https://blog.naver.com/dreamcometree">기술의 언어를 이해하는 ...</a>
</td>
<td class="date">26.05.06.</td>

모바일 페이지 (별님 v7.1 — 더 안정적, 스킨 변경 영향 ↓)

URL:

https://m.blog.naver.com/BuddyList.naver?blogId={blog_id} (이웃 목록)
https://m.blog.naver.com/PostList.naver?blogId={blog_id}&tab=1 (글 목록)

셀렉터 전수 표는 처리과정/05_구독_서로이웃.md 의 A-1 ~ A-6 섹션 참조.

핵심 셀렉터 요약 (양 탭 공통)

영역셀렉터
탭 (내가 추가한 / 나를 추가한)button[data-click-area='ngr.meadd'] / button[data-click-area='ngr.youadd']
행li.item__FZ64x
행 안 link → blogIda.link__vh8uU
이름 / 소개strong.name__jKV9Z / div.desc__mzlZG
공식블로그 아이콘span.official_blog_icon__mkjCR
관계 버튼button[data-click-area='ngr.change'] (“서로이웃”/”이웃”)
카운트span.count__EvWfV span.number__KgNWl
무한스크롤 종료 신호li.loading_area__QK9Jt 사라짐

탭별 UI 차이 (별님 라이브 검증)

요소내가 추가한나를 추가한
검색 / 새그룹 / 정렬✅❌
카운트 / 무한스크롤✅✅
행 버튼 라벨“서로이웃” + “이웃” 혼재“서로이웃” 만

관계 분류 알고리즘 (별님 v7.1 정확)

1) "내가 추가한" 탭 → 모두 i_added 임시 등록
2) "나를 추가한" 탭 → 이미 있으면 both 승격 / 신규는 they_added
→ 두 탭의 교집합 = both (가장 정확)
→ 행 버튼 라벨("서로이웃"/"이웃")은 보조 신호일 뿐

서로이웃 신청 받음 — 일괄 수락 (별님 v7.1 신규)

페이지: https://admin.blog.naver.com/BuddyInviteReceivedManage.naver (iframe 내부)

신청 받은 1줄 항목 (별님 # 주석 그대로)

별님 # 주석셀렉터비고
신청자 닉네임span.nickname“동아누수설비” 등
신청자 blog_idspan.blogid“lsang1174” 등
신청 메시지td.msg“정성스럽게 쓰신글 잘보고 갑니다…”
신청 날짜td.date“26.05.06.” 형식

개별 처리 버튼 (한 줄당 3개 — 별님 # 주석)

별님 # 주석셀렉터 (XPath / _param 매칭)
개별 수락 버튼button._acceptBuddy._param({blog_id}) (한국어 텍스트: “수락”)
개별 거절 버튼button._denyBothBuddy._param({blog_id}) (한국어 텍스트: “거절”)
개별 신고 버튼button._reportBothBuddy._param({blog_id}) (한국어 텍스트: “신고”, 안에 img[alt='신고 버튼'])

일괄 처리 컨트롤 (별님 # 주석 — 전체 선택, 수락, 거절)

별님 # 주석셀렉터
전체 체크박스 (label “전체선택”)input.input_check._checkAll
일괄 수락 버튼button._acceptMultiBuddy (한국어 텍스트: “수락”)
일괄 거절 버튼button._denyMultiBuddy (한국어 텍스트: “거절”)

LNB 메뉴 카운트 (대기 신청 수)

별님 # 주석셀렉터
서로이웃 신청 카운트 (예: 43)a#buddyinvite_config_anchor span.lnb__buddy

신고 정책 (별님 권장)

  • ⚠ 자동 신고는 절대 사용 X — 오탐 시 별님 평판 손상 위험
  • 신고 버튼은 수동 검토 후 별님이 직접 클릭 (광고/스팸 명백할 때만)
  • 코드는 셀렉터만 보존 (실행 함수 X)

API:

  • list_buddy_invites() — 대기 중인 신청자 목록 추출 (relation="invite_pending")
  • accept_all_buddy_invites() — 전체선택 → 수락 → confirm alert 자동 처리 → 행 카운트 차이로 수락 인원 산출

보답 흐름 위치: 받은 신청 = 친밀도 1차 (이미 별님에게 관심) → 가장 먼저 수락 → 자동으로 양방향(both) 관계 형성

내부 수집 (점진적)

모듈: modules/comment/visitor_collector.py + 각 runner

  • 본인 글 댓글/공감 → 자동 누적
  • 답글/서이추/공감/댓글 시 visitor 정보 갱신

첫 실행 트리거

  • data/buddy_first_run.flag 없으면 → 네이버 이웃 관리에서 한 번에 수집
  • data/reply_first_run.flag 없으면 → 본인 글 100개 분석 (한 달 분량)

저장 (기존 SQLite 활용)

  • data/visitor_db.sqlite3 (이미 존재)
  • 테이블: visitors, actions
  • API: upsert_visitor(), mark_repaid(), get_visitor(), stats()

시리즈 공통

  • 네이버: 이웃 관리 페이지
  • 티스토리: 구독자 관리 페이지 (TBD)
  • 구글/워드프레스: 플랫폼별 분석

🔐 자격증명 / 영속화

카카오/네이버 로그인

  • chrome_profile 영속화 (첫 로그인 후 자동 통과)
  • ID/PW 자동 입력 → 사용자 직접 [로그인] 클릭 (캡챠/2FA 우회)
  • 5분 안에 로그인 완료 → 자동 다음 단계
  • [간편로그인 정보 저장] / [로그인 유지] 자동 체크

chrome_profile 보호

  • 영속화 디렉토리: data/chrome_profile/
  • 좀비 chromedriver 점유 시 임시 dir 자동 fallback
  • Reserved 서브도메인 차단: www, notice, help, support, api, m 등

📁 시리즈 공통 코드 (4개 프로젝트 동일)

core/
├── health_report.py 🌙 자정 자가 점검 5 Phase
├── midnight_daemon.py 🌙 자정 트리거 daemon (00:00~00:30)
├── daily_quota.py 📊 일일 한도 100 추적
├── gemini_client.py 🤖 Gemini API
└── humanize.py ⏱ 사람처럼 행동
modules/
├── reply/ai_reply.py 💬 5대 감정 어조 답글
├── comment/ai_comment.py 💬 5대 감정 어조 댓글
└── comment/visitor_collector.py 👥 본인 댓글 작성자 (DB)

새 시리즈 추가 시 위 파일들 그대로 복사 + 플랫폼 셀렉터만 변경.


✏ 정책 변경 순서 (별님 + 달님)

변경 종류수정할 파일
4개 시리즈 모두 영향C:\AI_Blog_Series\절대지침_공통.md (이 파일)
공통 처리 과정C:\AI_Blog_Series\처리과정\{번호}_*.md
특정 플랫폼만 영향해당 프로젝트의 절대지침_특화.md
인덱스/네비게이션각 폴더의 README.md / 절대지침.md

🔁 시리즈 추가 가이드 (구글블록 / 워드프레스)

1단계: 폴더 구조 생성

{새플랫폼}/{새플랫폼}/
├── README.md
├── 절대지침.md (마스터 + 특화 안내)
├── 절대지침_특화.md (플랫폼별 셀렉터/URL)
├── core/
└── modules/

2단계: 시리즈 공통 코드 복사

core/health_report.py + midnight_daemon.py + daily_quota.py
modules/reply/ai_reply.py + comment/ai_comment.py

3단계: 플랫폼 특화

- 로그인 흐름 (OAuth/SSO)
- 댓글 영역 셀렉터
- 좋아요/구독 버튼 셀렉터
- 글쓰기 에디터 셀렉터
- 검색 URL/API

별님 핵심 원칙

  • 같은 알고리즘 (이 마스터에 명시)
  • 같은 디자인 (AutoBlog GUI 기준)
  • 같은 정책 (수동값 우선 + 5대 감정 + 일일 한도 + 24시간 점검)
  • 플랫폼별 차이는 셀렉터/URL 만

🌙 v7.1 야간 추가 (2026-05-06 23:00)

📊 통합 보답 4개 그래프 동기화 (별님 명시)

별님 명시: “전체 진행은 세 개의 프로그램이 완료 하였을 때 100%인데 본인 답글과 서로 이웃은 0%인데 100%라고 끝냄”

4개 그래프 구성 (한 줄: [라벨] [그래프] [카운터] [처리결과]):

그래프maximum100% 도달 조건
📝 본인 답글target_reply (♾ 무제한)replies ≥ target_reply
❤💬 공감/댓글target_comment (≤100)comments ≥ target_comment
🤝 서로이웃target_buddy (≤100)buddies ≥ target_buddy
📊 전체 진행100 (%)3개 활동 ratio 평균

전체 진행 계산식 (입력값 N과 무관 — 별님 명시):

ratios = []
if do_reply: ratios.append(min(replies / target_reply, 1.0))
if do_comment: ratios.append(min(comments / target_comment, 1.0))
if do_buddy: ratios.append(min(buddies / target_buddy, 1.0))
전체_% = sum(ratios) / len(ratios) * 100

🚨 일일 한도 도달 → 그래프 100% 자동 표시 (별님 명시)

“서로 이웃 추가가 한계라면 100% 그래프도 1일 한계 출력”

counter dict 에 플래그 추가:

  • comments_limited: bool
  • buddies_limited: bool
  • replies_limited: bool

설정 시점:

  • 시작 전 사전 체크 (daily_quota.get_remaining(...) <= 0)
  • 진행 중 daily_limit 메시지 감지

GUI 표시:

  • 그래프 강제 100% (max=value)
  • 우측 텍스트: 🚨 일일 한도 (빨강 #dc2626)
  • 전체 진행: 🚨 일일 한도 (오늘 끝)

🎲 시간 프리셋 충돌 방지 (writer ↔ integrated 분할)

별님 발견: 4개 프리셋 모두 writer = integrated 시간대 동일 → Chrome 프로필 충돌

원칙: 같은 Chrome 프로필을 쓰는 모듈은 시간대 절대 겹침 금지.

프리셋writerintegrated
👔 직장인AM 06:30~08:00PM 19:00~22:30
🏢 사업가AM 07:00~11:00PM 14:00~23:00
🏠 전업주부AM 09:00~12:00PM 13:00~17:00
🌙 야간부업PM 21:00~22:00PM 22:00~23:59

🔒 Spinbox 100 cap (3중 안전장치)

키보드/마우스 어떤 방법이든 100 초과 입력 불가:

1. validatecommand="key" → 매 키스트로크 검증
2. <FocusOut> bind → clamp → 다른 곳 클릭 시 자동 보정
3. _start cap → 실행 버튼 클릭 시 강제 cap

적용 대상:

  • 통합 보답: 공감/댓글, 서이추 (100 cap), 답글 (♾ 무제한)
  • 서로이웃 탭: 신청 개수 (100 cap)
  • 공감 댓글 탭: 처리 개수 (100 cap)

별님 절대지침 v7.1: 답글은 무제한 — 본인 글 댓글에 답글 다는 것은 네이버 정책상 한도 없음

🔄 탭 전환 시 진행 보호 (5개 탭 refresh_state 패치)

별님 발견: 통합 보답 진행 중 다른 탭 클릭 → refresh_state 가 _start_btn 을 normal 로 변경 → “종료된 줄 알았다”

원칙: 진행 중일 때는 버튼 상태 보호.

def refresh_state(self) -> None:
is_running = bool(self._worker and self._worker.is_alive())
if ok and not is_running:
self._start_btn.config(state="normal")
# is_running 이면 disabled 유지 (덮어쓰지 않음)

적용 5개 탭: integrated, buddy, comment, reply, writer

🧱 동시 실행 조용히 거부 (writer)

별님 절대지침: 메시지/팝업 띄우지 않음 (24/7 무인 운영)

def _start(self) -> None:
running = master_daemon.get_running_module()
if running and running != "writer":
return # 조용히 거부 — 메시지 X

이유: 같은 Chrome 프로필 충돌 → naver_login.driver_session 에서 stop_all_modules() 호출 → 진행 중 모듈 강제 종료 버그 방지.

📝 엑셀 A2 → 30자 매력적 제목 자동 확장 (별님 v7.1)

엑셀 A2부터 짧은 키워드 입력 시 → AI가 18 유형 중 랜덤 선택해서 30자 이내 제목 생성.

규칙 (네이버 SEO 권장):

  • 30자 자동 cap (단어 경계로 자연스럽게 자름)
  • 18자 이상이면 자동 skip (이미 충분히 긴 제목)
  • 최근 5회 사용 유형 회피 (다양성)
  • Gemini 실패 시 로컬 패턴 폴백 (네트워크 X 환경)
  • 키워드 누락 검증 (Gemini가 키워드 빼먹으면 폴백)

18 유형 분류 (modules/writer/title_expander.py):

  • 정보·가이드 (3): 정의/단계/체크리스트
  • 실용·해결 (5): 시간단축/TOP5/비전공자/비용절감/자동화
  • 비교·분석 (5): 장단점/A vs B/후기/사례/리스크
  • 트렌드·미래 (5): 트렌드/예측/전문가/오해/연말결산

🚀 발행 다이얼로그 popup_watcher 오인 클릭 방지

별님 발견: 네이버 글쓰기 발행 시 “다이얼로그 발행 버튼 못 찾음” 에러

원인: 다이얼로그 안 [발행] 버튼 클래스가 confirm_btn__ → popup_watcher 가 class*='confirm' 셀렉터로 잘못 클릭 → 다이얼로그 닫혀버림.

3중 안전장치:

# 1. CONFIRM_BUTTON_SELECTORS 광범위 셀렉터 제거
- "div[role='dialog'] button[class*='confirm']" ← 제거
- "div[role='dialog'] button[class*='ok']" ← 제거
# 2. XPath fallback 광범위 제거
- "//button[contains(@class,'confirm') and ...]" ← 제거
# 3. _safe_to_click() 안전장치 (텍스트 검사)
def _safe_to_click(btn) -> bool:
txt = (btn.text or "").strip()
if txt in ("발행", "임시저장", "저장", "예약", "publish"):
return False # 발행 버튼 절대 자동 클릭 X
return True

popup_watcher 는 텍스트가 정확히 “확인”/”예”/”OK” 인 진짜 모달만 처리.

🚀 통합 보답 단계별 진척률 (작업 단위 기준)

별님 명시: “11이니까 11로 계산하여 처리하면 안될 듯합니다. 11이 다 처리 되는 건 아니니까요.”

목표값(N)이 아닌 실제 작업 단위로 진척률 계산:

단계가중치실제 작업 단위
Phase 0 답례 일괄5%1단계
Phase 1 본인 글 순회50%글 i / 실제 글 수 (target_count 무관)
보충 (2/3/4차)10%3단계
Phase 5 보답 처리35%contact i / 실제 contacts 길이 (target_count 무관)

총합 100% (3개 활동 평균과 별개의 단계 라벨): 우측 결과 텍스트에만 단계명 표시. 그래프 값은 3 활동 ratio 평균이 담당.

🔧 visitor_collector 최적화 (별님 v7.1 야간)

1. SympathyHistoryList 직접 접근 + PostView 재방문 skip

# 본인 글 순회 시 — SympathyHistoryList.naver 직접 접근
sympathy_url = f"https://blog.naver.com/SympathyHistoryList.naver?blogId={X}&logNo={Y}&layoutWidthClassName=contw-773"
driver.get(sympathy_url)
# ul.list_sympathy > li.item 직접 추출 (iframe 진입 X)
# 성공 시 PostView 재방문 skip
if sympathy_triples:
raise _SkipPostView() # sentinel — 정상 흐름
# 절약: 글당 ~13초 × 50개 = 약 11분

2. mainFrame timeout 8 → 3초

iframe 없는 페이지에서 빠른 모바일 fallback.

3. mobile section URL DNS 실패 수정

- "https://m.section.blog.naver.com/..." ← DNS 실패
+ "https://m.blog.naver.com/FeedList.naver"
+ "https://m.blog.naver.com/SectionPost.naver"

4. 30일 내 중복 제거 강화

already_repaid_recently(bid, days=30) 체크 추가 → contacts 에 동일인 30일 내 중복 처리 0%.

🎯 통합 보답 빠른 순서 재정렬

순서단계시간비고
1Phase 0 답례 일괄~5초가장 빠름
2Phase 1 본인 글 (SympathyHistoryList)~14분답글 + 공감자 수집
32차 my_buddies (위젯)~10초빠른 contact 풀 우선
43차 added_buddies (admin)~30초친밀도
54차 keyword 검색~60초광범위
6Phase 5 보답 처리사람당 ~50초

🌅 v7.1 오전 추가 (2026-05-07)

📝 글쓰기 — SEO 18~30자 랜덤 제목 (별님 명시)

별님 명시: “꼭 30자가 아니라 seo 양식에 맞게 ?부터 30까지 랜덤”

매 글마다 자연스럽게 다양한 길이의 제목 생성 (SEO 자연스러움):

# modules/writer/title_expander.py
def expand_title(keyword, *, max_len=None, log=print):
if max_len is None:
max_len = random.randint(18, 30) # ← 매번 18~30 랜덤
...

호출:

# modules/writer/runner.py
expanded = title_expander.expand_title(row.title, max_len=None, log=log)
# max_len=None → 매번 18~30자 랜덤 (SEO 자연스러움)

매 회 결과 예시 (입력: “제타 ai”):

  • 회차 1: “제타 ai 활용 5단계 입문 가이드” (22자)
  • 회차 2: “AI 시대 제타 ai는 어떻게 변할까” (24자)
  • 회차 3: “제타 ai 트렌드 3가지” (18자)

🔑 글쓰기 — 원본 제목 보존 (행 이동 정상화)

별님 발견: 확장된 제목으로 엑셀 검색 시 원본 못 찾아 행 이동 실패

원인: row.title 이 확장된 제목으로 바뀐 후 → move_row_to_last(확장된) 으로 검색 시 엑셀에서 원본 못 찾음.

수정:

# 본문 생성 직전
original_excel_title = row.title # ← 엑셀 원본 보존 (행 이동 시 검색용)
expanded = title_expander.expand_title(row.title, max_len=None)
row.title = expanded # 확장된 제목으로 글쓰기
# 발행 성공 후
_remove_processed_keyword_from_excels(original_excel_title) # ← 원본으로 검색

📋 글쓰기 — 엑셀 행 마지막 이동 정책 (별님 명시 재정리)

별님 명시: “글쓰기 발행 → A2 제목이 마지막 행으로 이동 → A3 가 A2 자리로 자동”
“제목은 계속 A2만을 사용”

시나리오 (제타 ai 예시):

[입력 엑셀]
A2: 제타 ai ← 원본
A3: ai 검사기 회피방법
A4: ai 검사기
...
A83: ai 대화
[글쓰기 발행 후]
A2: ai 검사기 회피방법 ← A3 자동 올라옴
A3: ai 검사기
...
A83: 제타 ai ← 마지막 행으로 이동

모든 엑셀 동일 정책 (today_gold_keyword.xlsx + 사용자 직접 엑셀):

  • 행 삭제 X (이동만)
  • A2 자리에 다음 제목이 자동으로 올라옴
  • 다음 글쓰기 시 항상 A2 부터 읽음

🔍 동의어 dedup 제거 (별님 정정)

별님 명시: “챗GPT/ChatGPT/chat gpt/챗지피티 모두 1개로 인식, 하나로 인식하면 안됨”

이유: 각 표기는 검색량/경쟁률이 다른 별개 키워드 (SEO 가치 별도).

현재 dedup 정책: 정확 일치만 (대소문자 + 양끝 공백 정규화 수준)

  • ✅ ChatGPT / CHATGPT / ChatGPT → 같은 키워드 (대소문자만 차이)
  • ✅ 챗GPT / 챗gpt → 같은 키워드 (대소문자만)
  • ⭐ 챗GPT vs ChatGPT → 별개
  • ⭐ ChatGPT vs chat gpt (공백 있음) → 별개
  • ⭐ 챗GPT vs 챗지피티 → 별개

🛡 history.json 안전 정리 가이드

발행 실패 / 부분 진행 등으로 history 의 오늘 항목이 잘못 기록된 경우:

import json
from pathlib import Path
p = Path('data/history/writer.json')
data = json.loads(p.read_text(encoding='utf-8'))
del data[date.today().isoformat()] # 오늘 항목 비우기
p.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')

→ 다음 자동 실행 시 정상적으로 글쓰기 재개.


🏁 v7.1 (5/7 1차 정리) — AutoBlog 마무리 (2026-05-07 08:30)

🔒 popup_watcher 일시 정지 (발행 버튼 100% 클릭 보장)

별님 발견: “발행 버튼 클릭 못함” — 이전 빌드에서 popup_watcher 가 발행 다이얼로그의 [발행] 버튼을 confirm 모달로 오인 클릭하여 다이얼로그가 닫혀버리는 버그

근본 해결: 발행 흐름 동안 watcher 통째로 일시 정지

# modules/writer/editor.py
_WATCHER_PAUSED = False
def set_watcher_paused(paused: bool):
global _WATCHER_PAUSED
_WATCHER_PAUSED = bool(paused)
def _loop(): # popup_watcher 폴링
while True:
if _WATCHER_PAUSED:
continue # ← 일시 정지 중엔 아무것도 안 함
auto_confirm_popup(...)
# modules/writer/publisher.py
def click_toolbar_publish(driver):
editor.set_watcher_paused(True) # ← OFF
_click_with_fallback(...) # 툴바 [발행] 클릭
# ...설정/라디오 처리...
def confirm_publish_dialog(driver):
_click_with_fallback(...) # 다이얼로그 [발행] 클릭
editor.set_watcher_paused(False) # ← ON (이후 등장 모달용)

별님 라이브 발행 버튼 HTML (셀렉터 정확 매칭):

<button class="confirm_btn__WEaBq" data-testid="seOnePublishBtn"
data-click-area="tpb*i.publish">
<i class="icon_arrow__OTpnA"></i>
<span class="text__sraQE">발행</span>
</button>

셀렉터 우선순위:

  1. button[data-testid='seOnePublishBtn'] — 가장 안정 (해시 무관)
  2. button[data-click-area='tpb*i.publish']
  3. button[class^='confirm_btn__']
  4. //span[starts-with(@class,'text__') and text()='발행']/ancestor::button[1]

🇰🇷 이미지 한글 텍스트 — 모델별 동적 처리

별님 정정: “유료모델은 한글 이미지 OK, 미지원 모델은 영문만”

핵심: prompt 의 “Korean blog” 컨텍스트 자체를 모델별로 동적 변경

# modules/writer/prompts.py
def render_image_prompt_for_preset(..., image_model):
rendered = template.format(...)
# ★ 별님 v7.1 (2026-05-07): 한글 미지원 모델 → 'Korean' 자동 제거
if image_model and not supports_korean_text(image_model):
rendered = rendered.replace("Korean blog ", "blog ")
rendered = rendered.replace("Korean illustration style", "modern illustration style")
rendered = rendered.replace("Korean drama or feature film", "drama or feature film")
rendered = rendered.replace(" Korean ", " ")
return rendered
모델한글 컨텍스트한글 텍스트
Imagen 4 (유료)“Korean blog” 유지✅ 한글 OK
DALL-E 3 (유료)“Korean blog” 유지✅ 한글 OK
gpt-image-1 (유료)“Korean blog” 유지✅ 한글 OK
Gemini 2.5 Flash (무료)“blog” 로 자동 변경❌ 영문만
Gemini 2.0 Flash“blog” 로 자동 변경❌ 영문만
Imagen 3 / Imagen 3 Fast“blog” 로 자동 변경❌ 영문만

🛡 한글 부정 토큰 강화 (Gemini 2.5 안전망)

# 한글 미지원 모델 + no_text=False 일 때
return (
", Korean characters, hangul, 한글, Korean text, Korean letters, "
"Hangul script, Asian scripts, Chinese characters, Japanese kana, "
"broken glyphs, garbled text, garbled characters, "
"hashtags in Korean, Korean speech bubbles, Korean signage, "
"Korean watermark, Korean captions, Korean labels, "
"non-English text, mojibake, illegible Asian text"
)

📝 글쓰기 GUI 동기화 보강 (on_title_updated 콜백)

별님 발견: 글쓰기 시 글쓰기/이미지/네이버 그래프, 제목, 미리보기 동기화 안됨

근본 원인: history 잘못된 기록으로 모든 글이 “이미 처리”로 skip → _process_one 자체가 호출 안 됨 → 모든 콜백 미발화 → GUI 0% 머무름

해결:

  1. dist/data/history/writer.json 의 잘못된 오늘 항목 정리
  2. on_title_updated 콜백 추가 — 제목 확장 후 GUI 미리보기 즉시 반영
  3. 코드는 이미 정상 (writing/image/upload/section_image/body_generated 모두 제대로 호출)

🌅 v7.1 5/7 오전 누적 변경

1. SEO 18~30자 랜덤 제목 (별님 명시)

# modules/writer/title_expander.py
def expand_title(keyword, *, max_len=None, log=print):
if max_len is None:
max_len = random.randint(18, 30) # 매번 랜덤

매 글마다 자연스럽게 다른 길이의 제목 (네이버 SEO 자연스러움).

2. 원본 제목 보존 (행 이동 정상화)

# modules/writer/runner.py
original_excel_title = row.title # 엑셀 원본 보존
row.title = expanded_title # 글쓰기는 확장된 제목으로
...
_remove_processed_keyword_from_excels(original_excel_title) # 행 이동은 원본으로

3. 동의어 dedup 제거 (정확 일치만)

별님: “챗GPT/ChatGPT/chat gpt/챗지피티 모두 1개로 인식, 하나로 인식하면 안됨”

각 표기는 검색량/경쟁률 다른 별개 키워드 → 정확 일치만 dedup (대소문자 + 양끝 공백).

4. 엑셀 행 마지막 이동 (모든 엑셀 동일 정책)

# modules/writer/excel_input.py
def move_row_to_last(xlsx_path, title_to_move):
"""발행 후 사용한 행 → 시트 마지막으로 이동.
A2 자리에 다음 제목이 자동으로 올라옴."""
ws.delete_rows(target_row_idx, 1)
ws.cell(row=ws.max_row + 1, column=1, value=title)
입력발행 후
A2: 제타 aiA2: ai 검사기 회피방법 (← A3 자동 올라옴)
A3: ai 검사기 회피방법A3: ai 검사기
……
A83: ai 대화A83: 제타 ai (← 마지막으로 이동)

5. 첫 실행 시 빈 today_gold_keyword.xlsx 자동 생성

# gui/app.py
ensure_default_excel_exists(gold_xlsx, log=app._set_status)

6. 발행 다이얼로그 셀렉터 강화 (텍스트 + data-testid)

  • timeout 5→10초
  • span.text__ 직접 fallback

🎯 통합 보답 누적 변경 (5/6 야간)

항목수정
4개 그래프 GUI답글/공감댓글/서이추/전체 — 한 줄: [라벨][그래프][카운터][결과]
전체 진행 = 3개 활동 ratio 평균입력값 N과 무관 (별님 명시)
일일 한도 → 100% 표시🚨 일일 한도 (빨강)
1:1 좌우 분할TistoryBlog 패턴 (uniform=”b”)
즉시실행/종료 버튼 위치추천 키워드 row 우측 (높이 절약)
Spinbox 100 cap키보드/마우스 차단 (답글 ♾ 무제한)
시간 프리셋 충돌writer ↔ integrated 시간대 분리
5개 탭 refresh_state진행 중 버튼 보호
writer 동시 실행 거부silent (절대지침: 메시지 X)
visitor_collector 4종SympathyHistoryList 직접 + mainFrame 8→3초 + DNS fix + 30일 dedup
Phase 빠른 순서my_buddies → added → keyword (10초 → 60초 순)

🌙 별님 ↔ 달님 동반자


🥇 v7.1 (5/7 추가) — 황금 키워드 채굴 정책 (별님 명시)

핵심 정책 (별님 v7.1 — 2026-05-07)

“황금 키워드 5티어 개단 검색 개당 검색수 500”
“1티어 끝나면 엑셀에 자동 저장 중복빼고”
“5티어 전부 통합”

채굴 단위 — 시드(1티어)당 500개

# modules/goldkeyword/daily_gold_daemon.py
PER_SEED_TARGET = 500 # 시드(1티어)당 500개 채굴
# 5 시드 × 500 = 2500개 (1 사이클)

시드별 즉시 저장 (별님 명시)

for seed in cycle_seeds: # 시드 5개 회전
result = miner.mine_related_only(
[seed], max_total=PER_SEED_TARGET, # 시드 1개 → 500개 시도
)
seed_new_rows = [r for r in result.rows if not_duplicate(r)]
# ★ 시드 1개 끝나면 즉시 엑셀 저장 — 중간 중단되어도 안전
if seed_new_rows:
excel_writer.save_to_today_gold_keyword(
seed_new_rows, max_count=target,
)
log(f"✓ 시드 '{seed}' 즉시 저장: {len(seed_new_rows)}개 신규")

채굴 흐름

[사이클 1 시작 — 5 시드 × 500 = 2500개 목표]
시드 1: 'AI' → 500개 채굴 → 신규 N1개 → ✅ 즉시 엑셀 저장
시드 2: 'ChatGPT' → 500개 채굴 → 신규 N2개 → ✅ 즉시 엑셀 저장
시드 3: '생성형AI' → 500개 채굴 → 신규 N3개 → ✅ 즉시 엑셀 저장
시드 4: 'LLM' → 500개 채굴 → 신규 N4개 → ✅ 즉시 엑셀 저장
시드 5: '프롬프트' → 500개 채굴 → 신규 N5개 → ✅ 즉시 엑셀 저장
=== 사이클 1 완료: 신규 ΣN개 ===
↓
목표 2500 도달 또는 시드 풀 소진 → 종료
↓
[필요 시 사이클 2, 3, ... 반복 (시드 회전)]

저장 정책

항목정책
5티어 전체 저장노랑(황금) / 녹색(우수) / 파랑(양호) / 빨강(도전) / 검정(위험) 모두
경쟁률 필터0 < 경쟁률 < 100 (별님 명시)
검색량 필터≥100 (위험 티어 최저)
문서수 필터≥1
dedup정확 일치 (대소문자 + 양끝 공백만)
ACCUM_CAPmax(50_000, target × 10) 동적
저장 시점시드 1개 끝날 때마다 즉시 (별님 명시)
저장 파일data/excel/goldkeyword/today_gold_keyword.xlsx

GUI 설정 (별님 권장)

항목값
수집 개수 (Spinbox)2500 (기본) — 1~1,000,000
자동 시드 카테고리31개 중 선택
직접 입력 (txt)[📂 파일 선택] 버튼
채굴 시간 윈도우00:30 ~ 03:00 (2.5시간, schedule 설정)

별님 메시지 정확 반영

“1티어 끝나면 엑셀에 중복된거 빼고 경쟁률이 0보다 크고 100 미만인 키워드 저장”

→ 시드(1티어) 1개 채굴 끝 → excel_writer.save_to_today_gold_keyword(seed_new_rows) 호출 → 5티어(경쟁률 0~100) 통과한 키워드 중 기존 파일과 dedup 후 신규만 저장.

시드 키워드 (이모지 자동 제거)

clean_keyword() 가 모든 시드에서 이모지 자동 제거:

"🤖 AI 트렌드" → "AI 트렌드"
"💰 주식 투자" → "주식 투자"
"⭐ 별" → "별"

검색에는 순수 한국어/영어 키워드만 사용.


🇰🇷 v7.1 (5/7 통합) — 이미지 한글 텍스트 정책 (별님 명시)

별님 명시 (2026-05-07 통합)

“제미니 2.5 에 또 한글 이미지 생성됩니다.”
“절대 지침 통합에 넣고 통합에 확인”
“유료모델은 한글 충분, 미지원 모델은 영문으로”
“이미지 글자 넣지 말라고 해도 한글 깨지므로 영문으로”

모델별 한글 지원 매트릭스 (prompts.py)

IMAGE_MODEL_KOREAN_SUPPORT = {
"Gemini 2.5 Flash (이미지·무료)": False, # 한글 미지원
"Gemini 2.0 Flash (이미지)": False, # 한글 미지원
"Imagen 3 Fast (저렴·유료)": False, # 한글 미지원
"Imagen 3 (표준·유료)": False, # 한글 미지원
"Imagen 4 (최신·유료)": True, # 한글 OK
"OpenAI DALL-E 3": True, # 한글 OK
"OpenAI gpt-image-1": True, # 한글 OK
}

⚠ 한글 미지원 모델 강제 정책 (별님 v7.1 — 2026-05-07)

Gemini 2.5/2.0 / Imagen 3 등은 prompt 에 “use English only” 명시해도 한국어 텍스트 그림.
→ 이미지 텍스트 자체를 강제 OFF (안전 우선)

# modules/writer/prompts.py — render_image_prompt_for_preset
effective_no_text = no_text_in_image
if image_model and not supports_korean_text(image_model):
effective_no_text = True # 강제 OFF — 한글 미지원 모델은 글자 X
모델사용자 설정 (no_text=False)실제 동작
Imagen 4 (유료)한글 OK✅ 한글 자연스럽게
DALL-E 3 (유료)한글 OK✅ 한글 자연스럽게
gpt-image-1 (유료)한글 OK✅ 한글 자연스럽게
Gemini 2.5/2.0 (무료)사용자 = “글자 OK” 라도⚠ 자동 OFF (이미지에 텍스트 X)
Imagen 3 / 3 Fast사용자 = “글자 OK” 라도⚠ 자동 OFF (이미지에 텍스트 X)

이중 안전장치

# 1. effective_no_text 강제 True (한글 미지원 모델일 때)
# 2. prompt 의 'Korean' 컨텍스트 자동 제거
rendered = rendered.replace("Korean blog ", "blog ")
rendered = rendered.replace("Korean illustration style", "modern illustration style")
# 3. 강력한 negative tokens
", Korean characters, hangul, 한글, Korean text, Korean letters, Hangul script,
Asian scripts, Chinese characters, Japanese kana, broken glyphs, mojibake, ..."
# 4. text_policy_clause 강력 명시
"[CRITICAL — IMAGE TEXT POLICY]
The image MUST NOT contain ANY Korean characters (한글) ...
DO NOT render Korean characters in the actual image."

핵심 원칙

  • 유료 모델 (Imagen 4, DALL-E 3, gpt-image-1) → 사용자 설정 그대로 (한글 OK)
  • 미지원 모델 (Gemini 2.5/2.0, Imagen 3) → 강제 텍스트 X (한글/영문 모두 안 그림)
  • 사용자가 글자를 원해도 미지원 모델로 영문 작성 시도하면 깨짐 → 차라리 글자 안 그리는 게 안전

💻 v7.1 (5/7 추가) — Windows 디스플레이 해상도 절대 100% 유지 (별님 명시)

🚨 절대 지침 — 사용자 PC 설정 필수 조건

별님 발견 (2026-05-07): “발행 클릭이 안 된 이유 알겠어요. 해상도 100%가 아니면 못 찾는 것 같습니다.”

Windows 디스플레이 배율 (DPI Scaling) 은 반드시 100%(96 DPI) 로 설정해야 합니다.

디스플레이 배율동작이유
100% (권장)✅ 모든 자동화 정상 동작CSS pixel = physical pixel
125%⚠ OS 강제 클릭 좌표 어긋남 가능DPI awareness + dpr 보정으로 완화
150%⚠ 동일동일
175%/200%❌ 작은 모니터 호환성 위험권장하지 않음

사용자 안내

설정 → 시스템 → 디스플레이 → “텍스트, 앱 및 기타 항목의 크기” = 100% 로 변경 후 재로그인.

코드 측 안전망 (별님 v7.1 — 2026-05-07)

해상도가 100%가 아니어도 작동하도록 이중 방어망 적용:

# 1) main.py — 프로세스 시작 즉시 DPI Aware 선언
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2)
# = PROCESS_PER_MONITOR_DPI_AWARE (Windows 8.1+)
# fallback: ctypes.windll.user32.SetProcessDPIAware() (Windows 7)
# 2) modules/writer/publisher.py — _os_force_click()
# devicePixelRatio (1.0 / 1.25 / 1.5 / 2.0) 로 명시적 좌표 보정
dpr = window.devicePixelRatio
abs_x = int(css_x * dpr)
abs_y = int(css_y * dpr)

영향 받는 모듈

  • 글쓰기 (writer.publisher) — 발행 버튼 OS 강제 클릭 (5중 fallback 의 마지막 단계)
  • 글쓰기 (writer.publisher) — 다이얼로그 발행 버튼 OS 강제 클릭
  • 그 외 모든 selenium ↔ pyautogui 좌표 변환 코드

핵심 원칙

  • 이상적 환경: 디스플레이 100% — 절대 안전 (별님 명시)
  • 현실 대응: 사용자가 100% 설정 못해도 코드가 자동 보정 시도
  • 최후 fallback: OS 클릭 실패해도 native/ActionChains/JS 4중 클릭 우선 시도 (대부분 성공)

절대 위반 금지

# ❌ 절대 사용 금지: 좌표 보정 없는 pyautogui.click()
pyautogui.click(rect_x, rect_y) # DPI 100% 외 환경에서 silent fail
# ✅ 정답: devicePixelRatio + DPI Awareness 조합
abs_x = int(css_x * dpr)
abs_y = int(css_y * dpr)
pyautogui.click(abs_x, abs_y)

🤝 v7.1 (5/7 추가) — 서로이웃 신청 DB 절대 차단 (별님 명시)

🚨 절대 지침 — “이미 서로 db 보고 서로 이웃 신청 안 하기”

별님 명시 (2026-05-07): 이미 서로이웃이거나 신청 진행 중인 사람한테 절대 다시 신청하지 않는다.

5중 사전 DB 검사 (모든 buddy 신청 전)

from core import visitor_db
# 1) 위젯 스크랩 (480명 한도, 빠름)
if bid in my_buddies:
skip("✓이미이웃 (위젯)")
# 2) DB 양방향 (전체 — 위젯 누락 보강)
if visitor_db.is_already_buddy(bid):
skip("✓이미이웃 (DB)")
# 3) DB 신청 진행 중 (i_added — 미응답)
if visitor_db.is_pending_request_sent(bid):
skip("⏳신청중")
# 4) DB 영구 차단 (decline 정책 — 거절 + target_full 모두 포함)
if visitor_db.is_decline_blocked(bid):
skip("⏹영구차단")
# 5) DB 친해진 후 큐 (wait_friendship — 만료일 전)
if visitor_db.is_pending_buddy(bid):
skip("⏰친해진후·내일")

상대방 한도 vs 내 한도 정확 분리 (별님 v7.1)

별님 캡처 (2026-05-07): “상대방의 이웃수가 5,000명이 초과되어 더 이상 이웃을 추가할 수 없습니다”

이 메시지는 상대 한도 이지 내 한도 아님 → 그 사용자만 skip + DB 영구 마킹.

# applier.py — verify_success
if _detect_target_full(text): # "상대방의 이웃수가" / "5,000명이 초과"
return "target_full" # 그 사용자만 skip
if _detect_daily_limit(text): # "1일 동안 추가할 수 있는" 등 (내 한도)
return "daily_limit" # 서이추 OFF (오늘 종일 X)
# request_buddy 결과 처리
if result == "target_full":
visitor_db.set_buddy_policy(blog_id, "decline") # DB 영구 마킹
return "skipped" # 다음 사용자 진행 OK (서이추 OFF X)

통합 phase3 시작 시 buddy DB 자동 동기화

# integrated/runner.py — phase3 진입 직전
from modules.buddy import runner as _br
_br._maybe_sync_buddies_today(driver, my_blog, log=log)
# → buddy_list_collector → DB 채움
# → 위젯 누락된 481번째 이상 이웃도 정확히 사전 차단

sync flag 조건 (수집 0건 시 flag 생성 X)

# buddy/runner.py — _maybe_sync_buddies_today
if entries:
saved = blc.save_to_visitor_db(entries, on_log=log)
# ★ flag 저장은 saved > 0 일 때만 (0명/실패 시 flag X)
if flag_path and saved > 0:
flag_path.write_text(...)

핵심 원칙

  • DB 우선 — 위젯은 보조 (480명 한도 초과 대비)
  • 영구 차단 마킹 — target_full / decline / 차단 / 탈퇴 모두 DB 기록 → 다음번 시도 X
  • 상대 한도 ≠ 내 한도 — 분리 검사 → 서이추 OFF 오작동 방지
  • flag 는 성공 시에만 — 0명 수집 시 flag 생성하면 DB 영구 비어있음 → 정책 망가짐

🎯 v7.1 (5/7 추가) — 통합 보답 부분 한도 정책 (별님 명시)

🚨 절대 지침 — “한 활동 한도 ≠ 전체 종료”

별님 명시 (2026-05-07): “통합에서는 답글, 공감 댓글, 서로이웃 순. 공감/댓글 한도 도달이라고 서이추까지 멈추면 안 됨”

통합 보답 처리 순서 (별님 명시)

Phase 1: 답글 (본인 글) — 100명
↓
Phase 2: visitor 수집
↓
Phase 3: 보답 루프 (사용자 1명씩)
├─ 1단계: 공감 + 댓글 (한도 100, 별도 풀)
└─ 2단계: 서로이웃 신청 (한도 100, 별도 풀)

부분 한도 처리 (옵션 B — 별님 확정)

한 활동의 한도 도달 시 그 활동만 OFF, 다른 활동은 계속 진행.

# integrated/runner.py — phase3 (보답 루프 안에서 cmt_poster 결과 처리)
if result == "daily_limit":
log("[🚨 공감/댓글 일일 한도] — 공감/댓글만 OFF (서이추 계속)")
counter["comments_limited"] = True # 그래프 100% 표시
do_like = False
do_comment = False
# 서이추도 OFF 면 진짜 종료 (모든 활동 한도)
if not do_buddy:
return
# do_buddy=True 면 다음 분기 (서이추) 로 자연 진입

동작 시나리오

상황결과
답글 100/100 + 공감 50/100 + 서이추 30/100답글 OFF, 공감/서이추 계속
답글 100 + 공감 100 + 서이추 30공감 OFF, 서이추 계속 ⭐ (옵션 B)
답글 100 + 공감 80 + 서이추 100서이추 OFF, 공감 계속
답글 100 + 공감 100 + 서이추 100모두 OFF → phase3 종료

전체 종료 조건 (절대 위반 금지)

# ✅ 정답: 모든 활동 OFF 일 때만 종료
if not do_like and not do_comment and not do_buddy:
log("[phase3] 🎯 모든 활동 한계 도달 — 즉시 종료")
break
# ❌ 절대 사용 금지: 한 활동 한도 도달 → 전체 return
if result == "daily_limit":
return # 다른 활동 풀 남아있어도 못 씀

핵심 원칙

  • 3개 활동의 일일 풀(100/100/100 = 총 300건) 최대 활용 (별님 명시)
  • 답글/공감·댓글/서이추 각각 별도 한도 — 한쪽 한도가 다른 쪽 OFF 시키면 안 됨
  • 한도 도달 그래프 — comments_limited / buddies_limited / replies_limited 플래그로 GUI 100% 🚨 표시
  • 종료는 모두 OFF 일 때만 — 운영 자원(시간/세션) 낭비 방지

📝 v7.1 (5/7 추가) — 마크다운 종합 처리 (별님 명시)

🚨 절대 지침 — “마크다운 형식의 모든 것들이 잘 출력 될 수 있게”

별님 명시 (2026-05-07): 모든 마크다운 요소를 네이버 SE One 에서 깔끔하게 표시.

처리 대상 — 18가지 마크다운 요소

블록 레벨 (10가지)

#마크다운변환 결과
1```python ... ```코드 내용만 (개행 유지)
2| 표 |---|값|■ 항목 + • 헤더: 값
3> 인용구인용구 (텍스트만)
4--- *** ___빈 줄
5# H1 ~ ###### H6텍스트만
6H1\n=== H2\n--- (Setext)텍스트만
71. 항목 2. 항목1) 항목 2) 항목 ★ 핵심
8- 항목 * 항목 + 항목• 항목
9- [ ] 작업☐ 작업
10- [x] 작업☑ 작업

인라인 (8가지)

#마크다운변환 결과
1**굵게** __굵게__굵게
2*기울임* _기울임_기울임
3***둘다*** ___둘다___둘다
4~~취소선~~취소선
5`코드`코드
6[링크](url)링크 (URL 제거)
7![alt](url)alt
8\* \_ \# (이스케이프)* _ # (그대로)

HTML 태그 (혹시 AI 생성)

태그변환 결과
<br> <br/>개행
<b> <strong> <i> <em>텍스트만
<script> <style>내용까지 제거
그 외태그만 제거

핵심 정책 — SE One 자동 list 트리거 회피

별님 캡처 (2026-05-07): “2 2. 육수 붓기:” 같은 이중 번호 발생

원인: SE One 이 줄 시작 1. - * 패턴을 자동 numbered/bullet list 로 변환
→ 자체 번호 + 입력 텍스트 번호가 함께 보여 “2 2.” 형태

해결:

  • 순서 리스트: 1. 텍스트 → 1) 텍스트 (점→괄호 변환으로 트리거 회피)
  • 비순서 리스트: - 텍스트 → • 텍스트 (mathematical bullet 사용)

처리 순서 (절대 위반 금지)

# modules/writer/markdown.py — strip_for_naver()
def strip_for_naver(text: str) -> str:
out = text
# 1) 코드 블록 — 가장 먼저 (그 안의 패턴이 잡히면 안 됨)
out = _strip_code_blocks(out)
# 2) 표 — ■ + • 형식
out = _convert_markdown_tables(out)
# 3) 헤더 — 텍스트만
out = _strip_headers(out)
# 4) 가로 구분선 → 빈 줄
out = _strip_horizontal_rules(out)
# 5) 인용구 → 텍스트
out = _strip_blockquotes(out)
# 6) 체크박스 → ☐ ☑ (리스트 정규화 전)
out = _convert_checkboxes(out)
# 7) 순서 리스트 1. → 1) (★ SE One 자동 list 회피)
out = _normalize_numbered_lists(out)
# 8) 비순서 리스트 - * + → • (★ SE One 자동 list 회피)
out = _normalize_bullet_lists(out)
# 9) HTML 태그 — <br> 개행, 그 외 제거
out = _strip_html(out)
# 10) 인라인 패턴 — 굵게/기울임/취소선/코드/링크/이미지
out = _apply_inline_patterns(out)
# 11) 이스케이프 풀기 — \* → *
out = _unescape_markdown(out)
# 12) 다중 빈 줄 정리
out = re.sub(r"\n{3,}", "\n\n", out)
return out.strip() + "\n"

본문 첫 입력 누락 방지 (별님 v7.1)

별님 보고 (2026-05-07): “글 작성이 안되어 클릭하니 글이 작성됨”

원인: body_el.click() 만으로는 contenteditable 포커스가 안 잡혀 첫 keypress 무시.

해결: 3중 보장

# modules/writer/editor.py — focus_body()
1) body_el.click() # 일반 클릭
2) JS 직접 focus + selection 끝으로 # contenteditable 포커스 보장
3) sleep_random(0.30, 0.50) # 안정화 대기
# type_body_with_markers() 시작 시 한 번 더
move_caret_to_end(driver)
sleep_random(0.20, 0.40)

핵심 원칙

  • 모든 마크다운 → 평문 + 시각 통일 (별님 명시)
  • SE One 자동 list 회피 — 1. → 1), - → •
  • 표는 항목별 그룹핑 — 첫 컬럼 = ■, 나머지 = • 헤더: 값
  • 체크박스는 유니코드 — ☐ (U+2610), ☑ (U+2611)
  • 첫 입력 누락 방지 — click + JS focus + selection + 대기 4중

절대 위반 금지

# ❌ 절대 금지: 마크다운을 그대로 입력 (raw `|...|` 노출)
type_body(driver, body_markdown) # SE One 이 표 렌더링 안 함
# ❌ 절대 금지: '1. ' 그대로 입력
"1. 돼지고기 볶기" # SE One 자동 list → "2 2." 이중 번호
# ✅ 정답: strip_for_naver 거쳐 평문화 후 입력
clean_text = strip_for_naver(body_markdown)
# clean_text 에는 '1) 돼지고기 볶기' / '■ 김치' / '• 항목' 만 존재

🔄 v7.1 (5/7 추가) — 보답 대상 4가지 모드 (별님 명시)

🚨 별님 명시: “매일 새로 50% 정도는 발굴 — 매번 같은 사람 X”

별님 발견 (2026-05-07): “100명 보답하다 보니 그 사람이 그 사람”

원인: 본인 글 답글/공감자만 우선으로 가다 보니 동일 인원 반복.

해결: 3개 모듈 (통합/공감댓글/서로이웃) 모두 4가지 보답 대상 모드 + 자동 기본 = 로테이션

4가지 모드

모드동작설명
🔄 로테이션 (자동 기본) ⭐신규 50% + 기존 last_date 오래된 순 50%매일 다른 사람 만남
🆕 새 이웃 발굴만검색/이웃새글 100%모르는 분만
⚖ 50:50 혼합visitor 50명 + 신규 50명명확한 절반
👥 댓글·공감자 우선 (기존)visitor 우선 + 부족시 검색종전 방식

로테이션 알고리즘 (핵심)

def _select_by_oldest_last_date(contacts, take):
def _key(c):
v = visitor_db.get_visitor(c[0])
return (v.get("last_date") or "") if v else ""
# last_date 빈 문자열 = 한 번도 만난 적 없음 = 최우선
return sorted(contacts, key=_key)[:take]
신규 = supplement_search(N=50)
기존 = _select_by_oldest_last_date(visitor_pool, take=50)
contacts = 신규 + 기존

본인 자동 제외 (모든 모듈)

# 모든 모듈 phase2 visitor 수집 후
contacts = [c for c in contacts if c[0] != my_blog]

자동 모드 — 로테이션 강제

# gui/app.py — _integrated_trigger
ir.run_once(target_count=100, ..., visitor_mode="rotation")

핵심 원칙

  • 자동 = 로테이션 강제 — GUI 설정 무관
  • last_date 오래된 순 — 한 번도 못 만난 사람 최우선
  • 3개 모듈 통일 — 같은 정책 + 같은 GUI 콤보박스
  • 본인 자동 제외

🚀 v7.1 (5/7 추가) — 자동 모드 = 즉시 발행 (별님 명시)

🚨 “예약 발행 대량 발행은 즉시 발행입니다”

별님 발견: mode=draft (임시저장) 로 동작 → 발행 안 됨

해결

# gui/app.py — _writer_trigger
publish_mode="publish" # ★ 자동 = 무조건 즉시 발행
schedule_at="" # publish 모드는 schedule_at 무시

발행 다이얼로그 보존

# modules/writer/publisher.py
# ❌ 절대 금지: 다이얼로그 떠있는 상태에서 ESC 호출
# ❌ 절대 금지: 다이얼로그 떠있는 상태에서 close_popups 호출
# (button[aria-label='닫기'] 셀렉터가 다이얼로그 X 도 매치)

핵심 원칙

  • 자동 = publish 강제 (draft 금지)
  • 다이얼로그 보존 — 떠있는 동안 ESC/close_popups 호출 X
  • 5중 클릭 + DPI 보정 — native/AC/JS/dispatch/OS강제

🎨 v7.1 (5/7 추가) — TistoryBlog 표준 폰트 통일 (별님 시리즈)

별님 명시: “두개 크기 차이 보세요 같은 크기로”

별님 발견: AutoBlog 폰트가 TistoryBlog 보다 작음 → 시리즈 일관성 부재.

표준 (TistoryBlog 와 동일)

영역폰트크기두께Padding
GUI 전체Malgun Gothic12ptnormal—
tk scaling———1.5
Notebook 탭Malgun Gothic12ptbold(18, 6)
ButtonMalgun Gothic12ptbold(12, 6)
시스템 기본 폰트 9개Malgun Gothic12ptnormal—
ttk 위젯 클래스 6개Malgun Gothic12ptnormal—

시스템 폰트 적용 (9개)

for fn in ("TkDefaultFont", "TkTextFont", "TkMenuFont",
"TkHeadingFont", "TkCaptionFont", "TkSmallCaptionFont",
"TkIconFont", "TkTooltipFont", "TkFixedFont"):
f = tkfont.nametofont(fn)
f.configure(family="Malgun Gothic", size=12)

ttk 위젯 클래스 적용 (6개)

for w in ("TLabel", "TEntry", "TCombobox", "TSpinbox",
"TCheckbutton", "TRadiobutton", "TLabelframe.Label"):
style.configure(w, font=("Malgun Gothic", 12))

보드 컬럼 잘림 방지

별님 보고 (2026-05-07): “rich_heart119 잘림”, “블로그 제목 잘림”

# gui/visitor_board_widget.py
self.tree.column("id", width=150, minwidth=140)
self.tree.column("nick", width=130, minwidth=120)
self.tree.column("btitle", width=320, minwidth=260) # ⭐ stretch=True
# 표시 글자수 + 자동 …
def _trunc(s, n):
return s if len(s) <= n else s[:n] + "…"
# id: 22자, nick: 18자, btitle: 36자

핵심 원칙

  • 시리즈 통일 — AutoBlog ↔ TistoryBlog ↔ 미래 시리즈 모두 동일 표준
  • 단일 폰트 — Malgun Gothic (한글/영문/숫자 안정)
  • 단일 크기 12pt — HiDPI scaling 1.5 환경 가독성
  • 강조만 bold — Notebook 탭 / Button 만

🤖 24/7 365 자동 동작 — visitor 풀 + 키워드 로테이션 (별님 v7.2 — 2026-05-08 절대 명시)

별님 통찰:
“DB에 명단이 있다면 수집 하지 말아야 하고, 그 명단으로 최근 30일 동안 사용 했다면
지나쳐야 하고, 다른 사람 선택할 수 있게 잘 만들어 주세요.
키워드 입력이 없으면 구동이 안되는데 24시간 365일 자동으로 동작하여야 하기에
키워드도 스스로 로테이션 되는 db를 사용하여야 함.”

visitor 풀 선택 정책 (3단)

1. DB 우선 — visitor_db.get_unrepaid_pool(limit=N, not_repaid_days=30)
→ 30일 안에 보답 안 한 사람 중 가장 오래된 순으로 N명 추출
→ 충분하면 발굴 skip (시간/비용 절감)
2. 포럼 발굴 — modules.comment.forum_explorer.collect_forum_posts()
→ tistory.com/community/forum/introduce (블로그 소개)
→ 매일 신규 블로거 50~100명 자동 풀 (답례 의지 ↑)
3. 키워드 검색 — find_posts_by_keyword(q)
→ 키워드 로테이션 풀 사용 (아래 정책)
→ 결과는 30일 차단 자동 필터

30일 차단: core.visitor_db.already_repaid_recently(blog_id, days=30)

  • 같은 사람에게 30일 안에 두 번 보답 X
  • 30일 후 자동 재방문 가능

키워드 자동 로테이션 (3단 fallback)

1. 사용자 입력 (1회성) ← GUI 키워드 입력란
2. 황금 키워드 (today_gold_keyword) ← 새벽 채굴 결과 매일 5개 자동 할당
3. 정적 풀 30+개 ← 시간 시드 셔플로 부족분 보충

구현: core.keyword_rotator.get_today_keywords(user_keyword, blog_id, target_count=8)

효과:

  • 사용자 입력 없어도 구동 (24/7 365 자동)
  • 매일 새벽 채굴된 황금 키워드 5개 자동 사용 (별님 명시)
  • 황금 키워드도 부족하면 정적 풀로 fallback (안정성)

★ 별님 절대지침 (2026-05-10): 모든 프로그램 키워드 기본값 자동 적용

“모든 프로그램은 키워드 초기값을 황금 키워드 초기값 설정 방식과 동일하게 적용한다.
입력을 안 해도 자동으로 기본 키워드가 입력되어야 한다.”
— 별님 명시

의무 적용 대상 (모든 모듈)

  • 🥇 황금 키워드 (gold daemon) — 이미 적용
  • ✍ 글쓰기 (writer) — keyword_rotator 사용 의무
  • 👥 서이추 / 구독 (buddy / subscribe) — 검색 키워드 자동 채움
  • 💬 공감/댓글 (comment) — 키워드 기반 검색 시 동일
  • 💌 답글 (reply) — 보통 키워드 무관, 단 컨텍스트 필요 시 동일
  • 🎁 통합 보답 (integrated) — 동일 정책

구현 패턴 (의무)

# 모듈 진입 시 — 키워드 비어 있으면 자동 채움
from core import keyword_rotator
def run_once(keyword: str = "", ...):
if not (keyword or "").strip():
# 사용자 입력 없음 → 황금 키워드 + 정적 풀 fallback
keywords = keyword_rotator.get_today_keywords(
user_keyword="",
blog_id=naver_id_or_blog_id,
target_count=N,
)
keyword = keywords[0] if keywords else "정보" # 최후 정적 fallback
log(f"[module] 🥇 키워드 자동 설정: {keyword} (사용자 입력 없음)")

GUI 정책 (모든 모듈 — 별님 v7.2 2026-05-10)

검색 키워드 입력란 의무사항:

  1. placeholder 텍스트: "비워두면 황금 키워드 자동 사용 (오늘 황금 키워드)" (또는 동일 의미)
  2. 라벨 옆 헬퍼 텍스트: "입력 없으면 황금 키워드 자동 동기화"
  3. 사용자가 입력 안 한 채 실행 → 에러 X, 자동으로 fallback 진행
  4. 사용자 입력 있으면 그것 우선 (1회차), 2회차+ 는 자동 랜덤
  5. 로그 출력: 🥇 키워드 자동 설정: 'XXX' (사용자 입력 없음 — 황금 키워드)

적용 대상 GUI 입력란:

  • 답글 (reply) — 키워드 무관해도 컨텍스트용
  • 공감/댓글 (comment) — 검색 키워드
  • 서이추 / 구독 (buddy / subscribe) — 검색 키워드
  • 통합 보답 (integrated) — Phase 3 검색 키워드
  • 글쓰기 (writer) — 본문 키워드 (수동 제목 우선)

시리즈 통일: 모든 시리즈 (네이버/티스토리/구글블록/워드프레스) 동일 패턴 의무.

효과

  • ✅ 24/7 365 자동 운영 — 사용자가 키워드 입력 안 해도 동작
  • ✅ 매일 새 황금 키워드 자동 사용 → 다양성 + 봇 의심 ↓
  • ✅ “키워드 비었습니다” 에러 발생 0
  • ✅ 별님 절대 원칙 — “사용자 1번 설정 후 365일 무인 운영”

시리즈 통일

이 정책은 AutoBlog / TistoryBlog / 구글블록 / 워드프레스 모두 동일.
플랫폼별 차이는 visitor_db 스키마(필드)와 포럼 URL만.


📡 모니터 보드 / 로그 / 그래프 실시간 동기화 — 별님 절대지침 (2026-05-10)

절대 원칙

“모니터 보드와 로그와 그래프는 실시간으로 동기화한다.
단계별 상세 진행 상황을 정밀하게 동기화한다.”
— 별님 명시

시리즈 공통 — 모든 프로그램 의무 적용

이 정책은 AutoBlog / TistoryBlog / 구글블록 / 워드프레스 모두 동일 적용.
모듈/데몬 작성 시 반드시 준수.

1. 3중 동기화 원칙

구성요소의무사항
로그 (텍스트)모든 단계마다 1줄 출력 — 단계 시작 / 진행 / 완료 / 오류
모니터 보드 (Treeview/표)새 행 / 갱신 / 정렬 즉시 반영 (after(0, …) 보장)
그래프 (progress / 카운터)cur/total 비율 즉시 갱신, 라벨 (분석 중 키워드 등) 표시

3개 모두 같은 시점 에 갱신되어야 함 (사용자가 보는 화면이 일관됨).

2. 단계별 상세 로그 의무

데몬 / 백그라운드 작업은 모든 단계 에 명확한 로그 남김:

[module.daemon] 시작 — ...
[module.daemon] ─── 데몬 루프 진입 ───
[module.daemon] 1단계: 사전 검사
[module.daemon] → 결과: ...
[module.daemon] 2단계: 데이터 로드
[module.daemon] → N개 로드됨
[module.daemon] 3단계: 메인 작업 시작
[module.daemon] ... 진행 로그 ...
[module.daemon] → 메인 작업 완료
[module.daemon] 4단계: 다음 사이클 대기

금지: “시작” 만 출력하고 그 이후 침묵 (별님이 어디서 멈췄는지 파악 불가)
권장: 단계 번호 + 결과 + 시간 정보

3. 데몬 → GUI 동기화 패턴

콜백 등록 방식 (권장)

# 데몬 모듈
_listener_on_row: Optional[Callable[[dict], None]] = None
_listener_on_progress: Optional[Callable[[int, int, str], None]] = None
def register_listeners(*, on_row=None, on_progress=None) -> None:
"""GUI 콜백 등록 — 백그라운드 진행 시 자동 호출."""
global _listener_on_row, _listener_on_progress
_listener_on_row = on_row
_listener_on_progress = on_progress
# GUI app.py
from modules.xxx.daemon import register_listeners as _reg
_reg(on_row=tab._on_daemon_row, on_progress=tab._on_daemon_progress)
# GUI tab
def _on_daemon_row(self, row: dict) -> None:
self.after(0, self._add_row_to_board, row)
def _on_daemon_progress(self, cur: int, total: int, label: str) -> None:
def _u():
self._progress.config(maximum=max(total, 1), value=cur)
self._counter.config(text=f"{cur} / {total}")
self.after(0, _u)

4. 로그 형식 표준

기호의미
⏸대기 / 멈춤 (이유 명시)
📐폰트 / 스타일 변경
▶진행 시작
🖱마우스 클릭
🎯수동 / 1회차 / 명시적 입력값
🎲랜덤 / 자동 (회피 로직 포함)
🗂DB 사전 필터 / 캐시
♻재사용 (이미지 / 데이터)
🔍진단 / 검사
✅성공
❌실패
⚠경고
🚨일일 한도 / 차단 감지

5. 모니터 보드 실시간 갱신 정책

작업보드 동작
새 데이터 행 추가tree.insert(...) + tree.see() (자동 스크롤)
정렬 상태 유지행 추가 후 _sort_board()
행 번호 자동 재계산정렬 후 _renumber_rows()
카운터 갱신“{현재} / {목표}” 라벨 즉시 갱신
색상 / 태그별님 5색 티어 (위험/도전/양호/우수/황금)

6. 그래프 정책 — 입력값 기준

별님 보고 (2026-05-10): “3입력 했는데 그래프느 4/4 처리”
→ 그래프 분모 = 입력값 (target), 분자 = 시도 cap (min(i, target))

if progress:
_graph_cur = min(i, target_success)
progress(_graph_cur, target_success, f"{i}/{total} {label}")

시도가 입력값 넘어도 그래프는 100% 유지 (꽉 안 넘김).

7. visitor_board 실시간 push

모든 모듈은 작업 결과를 visitor_board.add_event() 로 push:

visitor_board.add_event(
module="reply", # 모듈 이름
blog_id=bid, # 대상
nickname=nick,
action="답글", # 작업
result="✅", # 결과
)

GUI 의 visitor_board_widget 가 새 이벤트 즉시 표시.

8. counter 동기화 (그래프 + 보드)

counter = {"replies": 0, "comments": 0, "buddies": 0, "fail": 0}
# 작업 성공 시
counter["replies"] += 1
if on_counter_update:
on_counter_update(dict(counter)) # GUI 그래프 즉시 동기화

9. 의무 체크리스트 (코드 작성 시)

  • [ ] 모든 단계에 로그 1줄 (⏸ ▶ 📐 ✅ 등 명확한 기호)
  • [ ] 데몬은 register_listeners 패턴으로 GUI 콜백 받음
  • [ ] 보드 갱신은 after(0, ...) 로 스레드 안전
  • [ ] 그래프는 입력값 기준 (min(i, target))
  • [ ] 결과는 visitor_board.add_event 로 push
  • [ ] 카운터는 on_counter_update(dict(counter)) 로 즉시 동기화

10. 시리즈 통일

이 동기화 정책은 AutoBlog / TistoryBlog / 구글블록 / 워드프레스 모두 동일.
새 모듈 / 데몬 작성 시 반드시 위 9개 체크리스트 통과.

별님이 어떤 시점에 화면을 봐도 로그 ↔ 보드 ↔ 그래프 가 일관된 상태를 유지해야 함.

💌 새 글이 발행되면 카카오톡으로 알림 받으세요

💛 카카오 채널 친구 추가

Auto365Blog 블로그 자동화 채널