AutoPercenty3/titleManager/db_test2.py

206 lines
9.5 KiB
Python

import re
import random
import logging
from datetime import datetime
# =============================================================================
# TitleGenerator 클래스 (테스트에 필요한 부분만 발췌하여 최소 구현)
# =============================================================================
class TitleGenerator:
def __init__(self, locator_manager, browser_controller, logger, toggle_states, gpt_client):
self.logger = logger
self.browser_controller = browser_controller
self.locator_manager = locator_manager
self.toggle_states = toggle_states
# 실제 코드에서는 MongoDBManager 등을 초기화하지만,
# 테스트에서는 더미 객체를 사용하므로 여기서는 None 처리
self.forbidden_word_manager = None
self.gpt_client = gpt_client
# 실제 번역 라이브러리 대신, translate_product_name을 단순 반환으로 구현
self.translator = None
def translate_product_name(self, original_name: str) -> str:
# 테스트에서는 번역 없이 원본 상품명을 그대로 사용
return original_name
def is_word_forbidden(self, word: str) -> bool:
"""더미 금지어 매니저로 위임 (없으면 False 반환)"""
if self.forbidden_word_manager:
return self.forbidden_word_manager.is_word_forbidden(word)
return False
def is_valid_word(self, word: str) -> bool:
"""숫자만이거나 영어+숫자로만 이루어진 단어는 유효하지 않다고 판단"""
return not (word.isdigit() or re.fullmatch(r'[A-Za-z0-9]+', word))
def extract_special_words(self, original_name: str) -> list:
"""원본 상품명에서 숫자 또는 영어+숫자로만 이루어진 단어를 추출"""
return [word for word in original_name.split() if word.isdigit() or re.fullmatch(r'[A-Za-z0-9]+', word)]
def filter_invalid_words(self, words: list) -> list:
"""영어 또는 영어+숫자로만 이루어진 단어를 제외"""
return [word for word in words if not re.fullmatch(r'[A-Za-z0-9]+', word)]
def process_top_titles(self, top_titles: list) -> list:
"""검색 결과 상위 제목들에서 유효하지 않은 단어들을 제거"""
filtered_titles = []
for title in top_titles:
filtered_words = self.filter_invalid_words(title.split())
filtered_titles.append(' '.join(filtered_words))
return filtered_titles
def generate_product_title(self, original_name: str, keyword_name: str, search_result: list, product_category: str) -> str:
"""
상품명을 생성하는 메서드
1. 원본 상품명을 번역(테스트에서는 그대로 사용)
2. GPT Client를 통해 원본과 키워드의 관련성을 판단
3. 검색 결과에서 상위 제목과 가격을 추출하여 처리
4. 키워드, 상위 제목, 원본의 특수 단어 등을 합쳐 최종 키워드 목록을 생성
5. 금지어 필터링 후, GPT Client를 통해 최종 상품명을 생성하여 반환
"""
# 1. 번역 (여기서는 그대로 사용)
translated_name = self.translate_product_name(original_name)
self.logger.debug(f"translated_name: {translated_name}")
# 2. 관련성 판단 (더미 GPT Client 사용)
is_related = self.gpt_client.is_related_product(translated_name, keyword_name)
if not is_related:
self.logger.debug("원본상품명과 키워드 간 관련성이 낮아 추가 검증 필요.")
# 3. 검색 결과 처리: 상위 제목, 가격 추출
top_titles = []
top_prices = []
if search_result:
for product in search_result:
if "title" in product and "price" in product:
top_titles.append(product["title"])
top_prices.append(product["price"])
self.logger.debug(f"top_titles: {top_titles}")
self.logger.debug(f"top_prices: {top_prices}")
else:
self.logger.warning("검색 결과가 비어 있습니다.")
# 4. 검색된 제목 필터링
filtered_top_titles = self.process_top_titles(top_titles)
# 5. 키워드 상품명에서 첫 4개 단어 추출
essential_keywords = keyword_name.split()[:4]
self.logger.debug(f"essential_keywords (첫 4개): {essential_keywords}")
# [keyword_name]과 필터링된 제목들을 합쳐 단어 단위 분해 후 집합 처리
keyword_title = list(set(
word for title in [keyword_name] + filtered_top_titles
for word in title.split()
))
self.logger.debug(f"초기 keyword_title: {keyword_title}")
# 6. 유효하지 않은 단어 제거
keyword_title = [word for word in keyword_title if self.is_valid_word(word)]
self.logger.debug(f"keyword_title after filtering invalid words: {keyword_title}")
keyword_title = list(set(keyword_title))
self.logger.debug(f"final keyword_title after deduplication: {keyword_title}")
# 7. 원본 상품명에서 특수 단어 추출 후 포함
special_words = self.extract_special_words(original_name)
self.logger.debug(f"special_words from original_name: {special_words}")
keyword_title.extend(special_words)
keyword_title = list(set(keyword_title))
self.logger.debug(f"keyword_title including special words: {keyword_title}")
# 8. 필수 키워드 중 랜덤 2개 선택 후 추가
required_keywords = random.sample(essential_keywords, min(2, len(essential_keywords)))
self.logger.debug(f"randomly selected required_keywords: {required_keywords}")
keyword_title.extend(required_keywords)
keyword_title = list(set(keyword_title))
# 9. 금지어 필터링 (더미 forbidden_word_manager 사용)
keyword_title = [word for word in keyword_title if not self.is_word_forbidden(word)]
self.logger.debug(f"keyword_title after forbidden filter: {keyword_title}")
# 10. 최종 상품명 생성 (더미 GPT Client의 generate_product_name_next 호출)
product_title = self.gpt_client.generate_product_name_next(words=keyword_title, original_name=original_name, top_titles=top_titles)
self.logger.debug(f"final product_title: {product_title}")
return product_title
# =============================================================================
# 더미(Stub) 의존 객체 클래스들
# =============================================================================
class DummyLocatorManager:
def get_locator(self, category, locator_name):
return f"{category}_{locator_name}"
class DummyBrowserController:
def __init__(self):
self.page = None # 테스트에서는 사용하지 않음
class DummyGPTClient:
def is_related_product(self, translated_name, keyword_name):
# 테스트에서는 항상 관련 있다고 가정
return True
def generate_product_name_next(self, words, original_name, top_titles):
# 테스트용: 원본 상품명과 정렬된 단어들을 조합하여 반환
return f"{original_name} - {' '.join(sorted(words))}"
class DummyForbiddenWordManager:
def is_word_forbidden(self, word):
# 예를 들어, "bad"라는 단어는 금지어로 판단
return word.lower() == "bad"
# =============================================================================
# 테스트 함수: generate_product_title 메서드 검증
# =============================================================================
def test_generate_product_title():
# 로깅 설정
logger = logging.getLogger("TitleGeneratorTest")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter("%(levelname)s - %(message)s")
handler.setFormatter(formatter)
if not logger.handlers:
logger.addHandler(handler)
# 더미 토글 상태 (네이버 API 키 등 실제 사용되지 않음)
toggle_states = {"clientID": "dummy_id", "clientSecret": "dummy_secret"}
# 더미 의존 객체 생성
locator_manager = DummyLocatorManager()
browser_controller = DummyBrowserController()
gpt_client = DummyGPTClient()
# TitleGenerator 인스턴스 생성
title_generator = TitleGenerator(locator_manager, browser_controller, logger, toggle_states, gpt_client)
# 금지어 매니저를 더미 객체로 교체 (예: "bad"는 금지어)
title_generator.forbidden_word_manager = DummyForbiddenWordManager()
# 테스트용 샘플 입력값
original_name = "Super Deluxe Coffee Maker"
keyword_name = "Coffee Maker Deluxe"
search_result = [
{"title": "Best Coffee Maker", "price": 15000},
{"title": "Deluxe Espresso Machine", "price": 25000},
{"related_tags": ["coffee", "maker", "espresso"]}
]
product_category = "Kitchen Appliances"
# generate_product_title 메서드 호출
generated_title = title_generator.generate_product_title(
original_name=original_name,
keyword_name=keyword_name,
search_result=search_result,
product_category=product_category
)
print("\nGenerated Product Title:")
print(generated_title)
# =============================================================================
# 메인 실행: 테스트 함수 호출
# =============================================================================
if __name__ == "__main__":
test_generate_product_title()