autoTrans/option.py

200 lines
10 KiB
Python

class OptionHandler:
def __init__(self, page, logger, vertexAI):
self.page = page
self.logger = logger
self.vertexAI = vertexAI
def process_options(self):
"""옵션 상품을 처리하는 메서드"""
try:
# 1. 단일 옵션인지 판단
if self.is_single_option():
self.logger.debug("단일 옵션 상품입니다. 옵션 수정 과정을 생략합니다.")
return
# 2. 전체 옵션 체크박스 상태 확인
if not self.is_all_options_checked():
self.logger.debug("옵션이 일부만 체크된 상태입니다. 옵션 수정이 완료된 상품으로 판단하여 패스합니다.")
return
# 3. 가격 낮은 순 정렬 클릭
self.logger.debug("가격 낮은 순 정렬을 클릭합니다.")
self.page.click('button:has-text("가격 낮은 순")')
self.page.wait_for_load_state('domcontentloaded')
# 4. 옵션 정보 수집 및 번역
option_info = self.collect_options_info()
# Vertex AI를 통해 옵션명을 번역
self.logger.debug(f"수집된 원본 옵션 정보: {option_info['original_names']}")
translated_options = self.vertexAI.translate_options(option_info['original_names'])
self.logger.debug(f"번역된 옵션 정보: {translated_options}")
# 5. 번역된 옵션명 편집칸에 입력
self.logger.debug("번역된 옵션명을 입력합니다.")
self.apply_translated_options(translated_options, option_info['edit_fields'])
# 6. 옵션 선택 및 제한 처리
self.adjust_options(option_info['checkboxes'])
# 7. 저장 버튼 클릭
self.logger.debug("저장 버튼을 클릭합니다.")
self.page.click('button:has-text("저장하기")')
self.logger.debug("옵션 처리 완료.")
except Exception as e:
self.logger.debug(f"옵션 처리 중 오류 발생: {str(e)}")
return
def is_single_option(self):
"""단일 옵션 상품 여부를 확인"""
try:
radio_group = self.page.query_selector('div.ant-row.css-1li46mu')
option_radio = radio_group.query_selector("//label[span[text()='옵션 상품등록']]//input[@type='radio']")
single_radio = radio_group.query_selector("//label[span[text()='단일 상품등록']]//input[@type='radio']")
return single_radio.is_checked() and not option_radio.is_checked()
except Exception as e:
self.logger.debug(f"단일 옵션 확인 중 오류 발생: {str(e)}")
return False
def is_all_options_checked(self):
"""전체 옵션 체크박스 상태를 확인 (전체 체크 여부)"""
try:
checkbox = self.page.query_selector('#productMainContentContainerId .ant-checkbox-wrapper-checked')
if checkbox:
return True
checkbox_partial = self.page.query_selector('#productMainContentContainerId .ant-checkbox-indeterminate')
return checkbox_partial is None # 일부 체크 시 False
except Exception as e:
self.logger.debug(f"전체 옵션 체크박스 확인 중 오류 발생: {str(e)}")
return False
def collect_options_info(self):
"""옵션 정보를 수집 (이미지, 옵션명, 편집 필드, 가격, 체크박스 정보 포함)"""
option_info = {
'original_names': {},
'edit_fields': {},
'checkboxes': [],
'images': {},
'prices': {} # 가격 정보 추가
}
try:
# 총 옵션 갯수 수집
total_options_selector = '#productMainContentContainerId label.ant-checkbox-wrapper'
total_options_element = self.page.query_selector(total_options_selector)
if total_options_element:
total_options_text = total_options_element.inner_text()
total_options_count = int(''.join(filter(str.isdigit, total_options_text))) # 숫자만 추출
else:
total_options_count = 0 # 옵션 갯수를 찾지 못할 경우 기본값
self.logger.debug(f"총 옵션 갯수: {total_options_count}")
# 옵션 정보를 수집 (총 옵션 갯수만큼 반복)
for i in range(1, total_options_count + 1):
try:
# 옵션명 수집
original_name_selector = f'#productMainContentContainerId li:nth-child({i}) .Body3Regular14'
original_name_element = self.page.query_selector(original_name_selector)
original_name = original_name_element.inner_text() if original_name_element else None
if original_name:
# 옵션명 기준으로 수집 항목 구성
option_info['original_names'][f'origin_option_{i}'] = original_name
# 옵션 편집 필드 수집
edit_field_selector = f'#productMainContentContainerId li:nth-child({i}) input.ant-input'
edit_field_element = self.page.query_selector(edit_field_selector)
if edit_field_element:
option_info['edit_fields'][original_name] = edit_field_element
# 옵션 체크박스 수집
checkbox_selector = f'#productMainContentContainerId li:nth-child({i}) input[type="checkbox"]'
checkbox_element = self.page.query_selector(checkbox_selector)
if checkbox_element:
option_info['checkboxes'].append(checkbox_element)
# 옵션 이미지 수집
image_selector = f'#productMainContentContainerId li:nth-child({i}) img.sc-gbvfcU.ezktkd'
image_element = self.page.query_selector(image_selector)
if image_element:
image_url = image_element.get_attribute('src')
option_info['images'][original_name] = image_url
else:
option_info['images'][original_name] = None # 이미지가 없으면 None
# 가격 정보 수집
price_selector = f'#productMainContentContainerId li:nth-child({i}) sup'
price_element = self.page.query_selector(price_selector)
if price_element:
price_text = price_element.inner_text().replace(",", "").replace("", "").strip()
if " - " in price_text:
low_price, high_price = map(int, price_text.split(" - "))
else:
low_price = high_price = int(price_text)
option_info['prices'][original_name] = {'low_price': low_price, 'high_price': high_price}
except Exception as e:
self.logger.debug(f"옵션 {i} 수집 중 오류 발생: {str(e)}")
except Exception as e:
self.logger.debug(f"옵션 정보 수집 중 오류 발생: {str(e)}")
return option_info
def apply_translated_options(self, translated_options, edit_fields):
"""번역된 옵션명을 편집칸에 입력"""
try:
for key, translated_name in translated_options.items():
option_number = key.split('_')[-1] # 'trans_option_1'에서 '1' 추출
edit_field = edit_fields.get(f'edit_option_{option_number}')
if edit_field:
edit_field.fill(translated_name)
except Exception as e:
self.logger.debug(f"번역된 옵션명을 입력하는 중 오류 발생: {str(e)}")
def adjust_options(self, checkboxes):
"""옵션 체크 상태 조정"""
try:
if len(checkboxes) > 3:
self.logger.debug("옵션이 3개 이상이므로 가장 낮은 옵션을 체크 해제합니다.")
checkboxes[0].click()
if len(checkboxes) > 10:
self.logger.debug("옵션이 10개 이상이므로 초과 옵션을 체크 해제합니다.")
for i in range(10, len(checkboxes)):
checkboxes[i].click()
except Exception as e:
self.logger.debug(f"옵션 체크 조정 중 오류 발생: {str(e)}")
def check_options(self, option_info):
"""옵션 체크 로직: 모든 옵션 체크 해제 후 다시 선택"""
try:
# 전체 옵션 체크박스 체크 해제
total_checkbox_selector = '#productMainContentContainerId label.ant-checkbox-wrapper'
total_checkbox_element = self.page.query_selector(total_checkbox_selector)
if total_checkbox_element:
total_checkbox_element.click()
self.logger.debug("모든 옵션 체크 해제 완료")
# 옵션 갯수에 따라 선택 로직 진행
total_options_count = len(option_info['original_names'])
self.logger.debug(f"선택 가능한 옵션 수: {total_options_count}")
if total_options_count > 2:
# 3개 이상인 경우: 1번째 옵션을 제외하고 최대 10개까지만 체크
options_to_check = option_info['checkboxes'][1:self.max_selected_options + 1]
else:
# 2개 이하인 경우: 모두 체크
options_to_check = option_info['checkboxes']
# 선택된 옵션들 체크
for checkbox in options_to_check:
checkbox.click()
self.logger.debug(f"옵션 체크 완료: {checkbox}")
except Exception as e:
self.logger.debug(f"옵션 체크 중 오류 발생: {str(e)}")