수정중

This commit is contained in:
R5600U_PC 2024-09-27 13:10:12 +09:00
parent a39596c96d
commit 71a9b9a975
17 changed files with 10035 additions and 97 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,9 @@ class BrowserController:
self.browser = None
self.page = None
def get_page(self):
return self.page
def start_browser(self):
"""크롬 브라우저 실행 및 페이지 로딩"""
self.logger.debug('크롬 브라우저 실행 중...')
@ -114,15 +117,15 @@ class BrowserController:
}''')
if element_text:
print(f"가져온 텍스트: {element_text}") # 텍스트 확인용 로그
self.logger.debug(f"가져온 텍스트: {element_text}") # 텍스트 확인용 로그
# "총 xx개 상품"에서 숫자만 추출
count = int(''.join(filter(str.isdigit, element_text)))
return count
else:
print("요소를 찾을 수 없습니다.")
self.logger.debug("요소를 찾을 수 없습니다.")
return 0
except Exception as e:
print(f"상품 수를 가져오는 중 오류 발생: {e}")
self.logger.debug(f"상품 수를 가져오는 중 오류 발생: {e}", exc_info=True)
return 0
@ -150,7 +153,7 @@ class BrowserController:
self.logger.debug(f'총 상품수 : {total_count}')
return total_count
except Exception as e:
self.logger.debug(f"총 상품 개수 수집 중 오류 발생: {e}")
self.logger.debug(f"총 상품 개수 수집 중 오류 발생: {e}", exc_info=True)
return 0
def get_product_name(self, index):
@ -160,7 +163,7 @@ class BrowserController:
product_name_element = self.page.query_selector(product_name_xpath)
return product_name_element.inner_text().strip()
except Exception as e:
self.logger.debug(f"상품명 수집 중 오류: {e}")
self.logger.debug(f"상품명 수집 중 오류: {e}", exc_info=True)
return "수집 오류 발생"
def extract_image_urls(self):
@ -259,7 +262,7 @@ class BrowserController:
except Exception as e:
# 다이얼로그가 없거나 다른 문제가 발생한 경우
self.logger.debug(f"다이얼로그가 발견되지 않았거나 오류 발생: {e}")
self.logger.debug(f"다이얼로그가 발견되지 않았거나 오류 발생: {e}", exc_info=True)
def go_to_new_product_page(self):
"""신규 상품 등록 페이지로 이동"""
@ -267,7 +270,7 @@ class BrowserController:
self.page.click('span.ant-menu-title-content:has-text("신규 상품 등록")')
self.logger.debug("신규 상품 등록 페이지로 이동 완료.")
except Exception as e:
self.logger.debug(f"신규 상품 등록 페이지 이동 중 오류: {str(e)}")
self.logger.debug(f"신규 상품 등록 페이지 이동 중 오류: {e}", exc_info=True)
def get_product_edit_buttons(self):
"""현재 페이지의 세부사항 수정 및 업로드 버튼을 찾기"""
@ -292,7 +295,7 @@ class BrowserController:
return [buttons.nth(i) for i in range(count)]
except Exception as e:
self.logger.debug(f"상품 수정 버튼을 찾는 중 오류: {str(e)}")
self.logger.debug(f"상품 수정 버튼을 찾는 중 오류: {e}", exc_info=True)
return []
def open_product_edit_dialog(self, button):
@ -306,7 +309,7 @@ class BrowserController:
self.logger.debug("세부사항 수정 다이얼로그 열기 완료.")
self.page.wait_for_selector('div.ant-tabs-nav') # 다이얼로그가 완전히 로딩될 때까지 기다림
except Exception as e:
self.logger.debug(f"세부사항 수정 다이얼로그 열기 중 오류: {str(e)}")
self.logger.debug(f"세부사항 수정 다이얼로그 열기 중 오류: {e}", exc_info=True)
def click_detail_tab(self):
"""상세페이지 탭 클릭"""
@ -314,7 +317,7 @@ class BrowserController:
self.page.click('div.ant-tabs-tab:has-text("상세페이지")')
self.logger.debug("상세페이지 탭 클릭 완료.")
except Exception as e:
self.logger.debug(f"상세페이지 탭 클릭 중 오류: {str(e)}")
self.logger.debug(f"상세페이지 탭 클릭 중 오류: {e}", exc_info=True)
def click_option_tab(self):
"""상세페이지 탭 클릭"""
@ -322,7 +325,7 @@ class BrowserController:
self.page.click('div.ant-tabs-tab:has-text("옵션")')
self.logger.debug("옵션 탭 클릭 완료.")
except Exception as e:
self.logger.debug(f"옵션 탭 클릭 중 오류: {str(e)}")
self.logger.debug(f"옵션 탭 클릭 중 오류: {e}", exc_info=True)
def extract_image_urls(self):
"""상세페이지에서 이미지 URL 추출"""
@ -363,7 +366,7 @@ class BrowserController:
return image_urls
except Exception as e:
self.logger.debug(f"이미지 URL 추출 중 오류: {str(e)}")
self.logger.debug(f"이미지 URL 추출 중 오류: {e}", exc_info=True)
return []
def translate_image(self, url):
@ -372,22 +375,22 @@ class BrowserController:
self.whale_translator.translate_image(url)
self.logger.debug(f"이미지 번역 완료: {url}")
except Exception as e:
self.logger.debug(f"이미지 번역 중 오류: {str(e)}")
self.logger.debug(f"이미지 번역 중 오류: {e}", exc_info=True)
def paste_image_in_chrome(self, clipboardImageManager, url):
"""크롬으로 포커스를 옮기고 클립보드의 이미지를 붙여넣고 엔터 입력"""
try:
self.switch_to_chrome() # 크롬으로 포커스 이동
clipboardImageManager.process_clipboard(url) # 클립보드 내용을 처리
clipboard_content = pyperclip.paste()
if clipboard_content:
# clipboard_content = pyperclip.paste()
if clipboardImageManager.is_clipboard_image():
pyautogui.hotkey('ctrl', 'v') # 클립보드 이미지 붙여넣기
pyautogui.press('right') # 오른쪽 입력
self.logger.debug("이미지 붙여넣기 완료.")
else:
self.logger.debug("클립보드가 비어있습니다.")
except Exception as e:
self.logger.debug(f"이미지 붙여넣기 중 오류: {str(e)}")
self.logger.debug(f"이미지 붙여넣기 중 오류: {e}", exc_info=True)
def save_product_edit(self):
"""상품 수정 후 저장 버튼 클릭"""
@ -396,7 +399,7 @@ class BrowserController:
self.logger.debug("상품 수정 내용 저장 완료.")
self.page.keyboard.press("Escape") # ESC로 다이얼로그 닫기
except Exception as e:
self.logger.debug(f"저장 버튼 클릭 중 오류: {str(e)}")
self.logger.debug(f"저장 버튼 클릭 중 오류: {e}", exc_info=True)
def go_to_next_page(self):
"""다음 페이지로 이동"""
@ -425,7 +428,7 @@ class BrowserController:
return False
except Exception as e:
self.logger.debug(f"다음 페이지로 이동 중 오류 발생: {str(e)}")
self.logger.debug(f"다음 페이지로 이동 중 오류 발생: {e}", exc_info=True)
return False
def switch_to_chrome(self):
@ -442,7 +445,7 @@ class BrowserController:
self.logger.debug('크롬 창을 찾을 수 없습니다.')
self.logger.debug('크롬 창을 찾을 수 없습니다.')
except Exception as e:
self.logger.debug(f"크롬 포커스 전환 중 오류: {str(e)}")
self.logger.debug(f"크롬 포커스 전환 중 오류: {e}", exc_info=True)
@ -513,12 +516,12 @@ class BrowserController:
self.logger.debug(f"상품 {i}: {product_info}")
product_infos.append(product_info)
except Exception as e:
self.logger.error(f"상품 {i} 정보 수집 중 오류 발생: {str(e)}")
self.logger.error(f"상품 {i} 정보 수집 중 오류 발생: {e}", exc_info=True)
continue
return product_infos
except Exception as e:
self.logger.error(f"상품 정보 수집 중 오류 발생: {str(e)}")
self.logger.error(f"상품 정보 수집 중 오류 발생: {e}", exc_info=True)
return []
def click_modify_button_by_text(self, index):

View File

@ -8,7 +8,7 @@ import numpy as np
import cv2
import time
import os
import datetime
from datetime import datetime
import random
class ClipboardImageManager:
@ -25,7 +25,7 @@ class ClipboardImageManager:
try:
return pyperclip.paste() # 클립보드의 텍스트 데이터를 가져옴
except Exception as e:
self.logger.debug(f"클립보드 데이터를 가져오는 중 오류 발생: {e}")
self.logger.debug(f"클립보드 데이터를 가져오는 중 오류 발생: {e}", exc_info=True)
return None
# def set_image_to_clipboard(self, image):
@ -41,7 +41,7 @@ class ClipboardImageManager:
# win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
# win32clipboard.CloseClipboard()
def set_image_to_clipboard(self, image, crop_percentage=0.05, debug=False):
def set_image_to_clipboard(self, image, crop_percentage=0.03, debug=False):
"""
이미지를 클립보드에 넣는 함수 (Windows 전용, 크롭 )
@ -218,7 +218,7 @@ class ClipboardImageManager:
else:
self.logger.debug("클립보드에 이미지가 없습니다.")
except Exception as e:
self.logger.error(f"클립보드에서 이미지를 가져오는 중 오류 발생: {e}")
self.logger.error(f"클립보드에서 이미지를 가져오는 중 오류 발생: {e}", exc_info=True)
finally:
win32clipboard.CloseClipboard()
@ -231,11 +231,11 @@ class ClipboardImageManager:
win32clipboard.EmptyClipboard()
self.logger.debug("클립보드가 비워졌습니다.")
except Exception as e:
self.logger.error(f"클립보드를 비우는 중 오류 발생: {e}")
self.logger.error(f"클립보드를 비우는 중 오류 발생: {e}", exc_info=True)
finally:
win32clipboard.CloseClipboard()
def crop_image(self, image, crop_percentage=0.05):
def crop_image(self, image, crop_percentage=0.01):
"""이미지를 주어진 퍼센트만큼 크롭하는 함수"""
width, height = image.size
left = width * crop_percentage
@ -253,7 +253,7 @@ class ClipboardImageManager:
self.logger.debug(f"크롭 전 이미지 저장됨: {original_image_path}")
# 3%, 5%, 7% 크롭 이미지 저장
crop_alternatives = [0.03, 0.05, 0.07]
crop_alternatives = [0.01, 0.02, 0.03]
for crop in crop_alternatives:
left_alt = width * crop
top_alt = height * crop
@ -280,7 +280,7 @@ class ClipboardImageManager:
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
self.logger.debug("이미지가 클립보드에 저장되었습니다.")
except Exception as e:
self.logger.error(f"이미지를 클립보드에 저장하는 중 오류 발생: {e}")
self.logger.error(f"이미지를 클립보드에 저장하는 중 오류 발생: {e}", exc_info=True)
finally:
win32clipboard.CloseClipboard()
@ -292,5 +292,5 @@ class ClipboardImageManager:
image = Image.open(BytesIO(img_data))
return image
except Exception as e:
self.logger.error(f"Base64 이미지를 변환하는 중 오류 발생: {e}")
self.logger.error(f"Base64 이미지를 변환하는 중 오류 발생: {e}", exc_info=True)
return None

13
gui.py
View File

@ -19,7 +19,7 @@ class TranslationApp(QWidget):
self.browser_controller = BrowserController(self, self.logger)
self.whale_translator = WhaleTranslator(self, self.logger, secret_mode=True,vd_mode=True) # 디버그 모드 켜기
self.vertexAI = VertexAITranslator(self.logger, key_path)
self.optionHandler = OptionHandler(self.browser_controller.page, self.logger, self.vertexAI)
self.optionHandler = None
self.clipboardImageManager = ClipboardImageManager(self, logger, self.browser_controller)
@ -260,6 +260,10 @@ class TranslationApp(QWidget):
# 로그인 정보 저장
self.save_settings()
# 옵션 핸들러 새로 초기화
self.optionHandler = OptionHandler(self.browser_controller.page, self.logger, self.vertexAI)
def save_settings(self):
"""QSettings에 사용자 정보 저장"""
self.settings.setValue("admin/id", self.admin_id_input.text())
@ -378,7 +382,7 @@ class TranslationApp(QWidget):
self.running = False # 작업 종료 후 상태를 False로 전환
except Exception as e:
self.logger.debug(f'번역 작업 중 오류 발생: {str(e)}')
self.logger.debug(f"번역 작업 중 오류 발생: {e}", exc_info=True)
self.running = False
def pause_translation(self):
@ -406,7 +410,7 @@ class TranslationApp(QWidget):
self.detail_image_count += total_images
# 이미지 번역 작업 진행
for url, i in enumerate(image_urls):
for i, url in enumerate(image_urls):
current_image_count = i +1
if not self.running:
@ -436,8 +440,7 @@ class TranslationApp(QWidget):
self.optionHandler.process_options(max_option_count)
# 수정 후 저장
self.logger.debug('상품 세부사항 저장 중...')
self.browser_controller.save_product_edit()
self.optionHandler.save_option()
self.detail_progress_bar.setVisible(False)

155
option.py
View File

@ -3,6 +3,14 @@ class OptionHandler:
self.page = page
self.logger = logger
self.vertexAItranslator = vertexAI
self.option_info = {
'original_names': {},
'edit_fields': {},
'checkboxes': [],
'images': {},
'prices': {} # 가격 정보 추가
}
def process_options(self, max_option_count=10):
"""옵션 상품을 처리하는 메서드"""
@ -18,50 +26,51 @@ class OptionHandler:
return
# 3. 가격 낮은 순 정렬 클릭
self.logger.debug("가격 낮은 순 정렬을 클릭합니다.")
self.page.click('button:has-text("가격 낮은 순")')
self.page.wait_for_load_state('domcontentloaded')
self.low_order_click()
# 4. 옵션 정보 수집 및 번역
option_info = self.collect_options_info()
# Vertex AI를 통해 옵션명을 번역
self.logger.debug(f"수집된 원본 옵션 정보: {option_info['original_names']}")
translated_options = self.vertexAItranslator.translate_options(option_info['original_names'])
self.logger.debug(f"수집된 원본 옵션 정보: {self.option_info['original_names']}")
translated_options = self.vertexAItranslator.translate_options(self.option_info['original_names'])
self.logger.debug(f"번역된 옵션 정보: {translated_options}")
# 5. 번역된 옵션명 편집칸에 입력
self.logger.debug("번역된 옵션명을 입력합니다.")
self.apply_translated_options(translated_options, option_info['edit_fields'])
self.apply_translated_options(translated_options, self.option_info['edit_fields'])
# 6. 옵션 선택 및 제한 처리
self.adjust_options(option_info['checkboxes'], max_option_count)
self.adjust_options(self.option_info['checkboxes'], max_option_count)
# 7. 저장 버튼 클릭
# 7. 정리된 옵션을 다시한번 더 가격 낮은 순으로 정렬 클릭
self.low_order_click()
# 8. 저장 버튼 클릭
self.logger.debug("저장 버튼을 클릭합니다.")
self.page.click('button:has-text("저장하기")')
self.logger.debug("옵션 처리 완료.")
except Exception as e:
self.logger.debug(f"옵션 처리 중 오류 발생: {str(e)}")
self.logger.debug(f"옵션 처리 중 오류 발생: {e}", exc_info=True)
return
def is_single_option(self):
"""단일 옵션 상품 여부를 확인"""
"""단일 상품 상태 여부를 확인하는 메서드"""
try:
# 단일 상품등록 버튼 선택 여부 확인
single_option_selector = '#productMainContentContainerId > div.sc-TOgAA.fZvEqY > div.ant-row.css-1li46mu > div > label.ant-radio-button-wrapper.ant-radio-button-wrapper-checked.css-1li46mu > span.ant-radio-button.ant-radio-button-checked > input'
single_option_element = self.page.query_selector(single_option_selector)
# 단일 상품 등록 버튼이 선택되었는지 확인
single_option_xpath = "//div[@id='productMainContentContainerId']//label[contains(@class, 'ant-radio-button-wrapper-checked') and contains(., '단일 상품등록')]"
single_option_checked = self.page.query_selector(single_option_xpath) is not None
# 옵션 상품등록 버튼 선택 여부 확인
option_product_selector = '#productMainContentContainerId > div.sc-TOgAA.fZvEqY > div:nth-child(1) > div > label.ant-radio-button-wrapper.ant-radio-button-wrapper-checked.css-1li46mu > span.ant-radio-button.ant-radio-button-checked > input'
option_product_element = self.page.query_selector(option_product_selector)
# 옵션 상품 등록 버튼이 선택되었는지 확인
option_product_xpath = "//div[@id='productMainContentContainerId']//label[contains(@class, 'ant-radio-button-wrapper-checked') and contains(., '옵션 상품등록')]"
option_product_checked = self.page.query_selector(option_product_xpath) is not None
# 두 요소의 체크 상태에 따라 단일 상품 여부 결정
is_single = single_option_element is not None and option_product_element is None
self.logger.debug(f"단일 상품 여부: {'단일 상품입니다.' if is_single else '옵션 상품입니다.'}")
return is_single
# 두 요소의 상태를 기반으로 단일 상품 여부 결정
is_single = single_option_checked and not option_product_checked
self.logger.debug(f"단일 상품 여부: {'단일 상품입니다' if is_single else '옵션 상품입니다'}")
return is_single
except Exception as e:
self.logger.error(f"단일 옵션 확인 중 예외 발생: {e}", exc_info=True)
return False
@ -76,18 +85,18 @@ class OptionHandler:
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)}")
self.logger.error(f"전체 옵션 체크박스 확인 중 오류 발생: {e}", exc_info=True)
return False
def collect_options_info(self):
"""옵션 정보를 수집 (이미지, 옵션명, 편집 필드, 가격, 체크박스 정보 포함)"""
option_info = {
'original_names': {},
'edit_fields': {},
'checkboxes': [],
'images': {},
'prices': {} # 가격 정보 추가
}
# option_info = {
# 'original_names': {},
# 'edit_fields': {},
# 'checkboxes': [],
# 'images': {},
# 'prices': {} # 가격 정보 추가
# }
try:
# 총 옵션 갯수 수집
@ -104,35 +113,48 @@ class OptionHandler:
# 옵션 정보를 수집 (총 옵션 갯수만큼 반복)
for i in range(1, total_options_count + 1):
try:
# 옵션명 수집
original_name_selector = f'#productMainContentContainerId li:nth-child({i}) .Body3Regular14'
# 원본옵션명 수집
original_name_selector = f"div#productMainContentContainerId li:nth-child({i}) > div > div:nth-child(1) > div > div:nth-child(3) > div:nth-child(3) > span"
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
self.logger.debug(f"{i}번째 옵션명 수집완료. 나머지 필드 수집중...")
self.option_info['original_names'][f'origin_option_{i}'] = original_name
# 옵션 편집 필드 수집
edit_field_selector = f'#productMainContentContainerId li:nth-child({i}) input.ant-input'
edit_field_selector = f"div#productMainContentContainerId li:nth-child({i}) > div > div:nth-child(1) > div > div:nth-child(3) > div:nth-child(2) > div:nth-child(1) > span > input"
edit_field_element = self.page.query_selector(edit_field_selector)
if edit_field_element:
option_info['edit_fields'][original_name] = edit_field_element
self.option_info['edit_fields'][original_name] = edit_field_element
self.logger.debug(f"{i}번째 옵션편집필드 수집 완료 : {edit_field_element}")
else:
self.logger.debug(f"{i}번째 옵션편집필드 수집 실패▣ edit_field_element : {edit_field_element}")
# 옵션 체크박스 수집
checkbox_selector = f'#productMainContentContainerId li:nth-child({i}) input[type="checkbox"]'
# f"div#productMainContentContainerId li:nth-child({i}) > div > div:nth-child(1) > div > div:nth-child(1) > label > span > input"
checkbox_element = self.page.query_selector(checkbox_selector)
if checkbox_element:
option_info['checkboxes'].append(checkbox_element)
self.option_info['checkboxes'].append(checkbox_element)
self.logger.debug(f"{i}번째 옵션 체크박스 수집 완료 : {checkbox_element}")
else:
self.logger.debug(f"{i}번째 옵션 체크박스 수집 실패▣ checkbox_element : {checkbox_element}")
# 옵션 이미지 수집
image_selector = f'#productMainContentContainerId li:nth-child({i}) img.sc-gbvfcU.ezktkd'
# "div#productMainContentContainerId li:nth-child(1) > div > div:nth-child(1) > div > div:nth-child(2) > div > img"
# "div#productMainContentContainerId li:nth-child(2) > div > div:nth-child(1) > div > div:nth-child(2) > div > img"
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
self.option_info['images'][original_name] = image_url
self.logger.debug(f"{i}번째 옵션 이미지 수집 완료 : {image_element}")
else:
option_info['images'][original_name] = None # 이미지가 없으면 None
self.option_info['images'][original_name] = None # 이미지가 없으면 None.
self.logger.debug(f"{i}번째 옵션 이미지 수집 실패▣ image_element : {image_element}")
# 가격 정보 수집
price_selector = f'#productMainContentContainerId li:nth-child({i}) sup'
@ -143,26 +165,44 @@ class OptionHandler:
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}
self.option_info['prices'][original_name] = {'low_price': low_price, 'high_price': high_price}
self.logger.debug(f"{i}번째 옵션 가격정보 수집 완료 : {low_price} - {high_price}")
else:
self.logger.debug(f"{i}번째 옵션 가격정보 수집 실패▣ price_element : {price_element}")
except Exception as e:
self.logger.debug(f"옵션 {i} 수집 중 오류 발생: {str(e)}")
self.logger.error(f"{i}번째 옵션 수집 중 오류 발생: {e}", exc_info=True)
except Exception as e:
self.logger.debug(f"옵션 정보 수집 중 오류 발생: {str(e)}")
self.logger.error(f"옵션 정보 수집 중 오류 발생: {e}", exc_info=True)
return option_info
return self.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)
self.logger.debug(f"{key}번째 translated_name : {translated_name}")
# 원본 옵션명을 기준으로 참조
origin_option_key = key.replace('trans_', 'origin_') # 'trans_option_1'을 'origin_option_1'로 변환
original_name = self.option_info['original_names'].get(origin_option_key)
if original_name:
edit_field = edit_fields.get(original_name) # 원본 옵션명으로 필드 참조
self.logger.debug(f"{key}번째 번역옵션 필드 : {edit_field}")
if edit_field:
edit_field.fill(translated_name) # 필드에 번역된 옵션명 입력
self.logger.debug(f"{key}번째 translated_name : [{translated_name}] 입력 완료")
else:
self.logger.debug(f"{key}번째 옵션 필드가 없습니다.")
else:
self.logger.debug(f"원본 옵션명을 찾을 수 없습니다: {origin_option_key}")
except Exception as e:
self.logger.debug(f"번역된 옵션명을 입력하는 중 오류 발생: {str(e)}")
self.logger.error(f"번역된 옵션명을 입력하는 중 오류 발생: {e}", exc_info=True)
def adjust_options(self, checkboxes, max_option_count):
"""옵션 체크 상태 조정"""
@ -176,7 +216,7 @@ class OptionHandler:
for i in range(max_option_count, len(checkboxes)):
checkboxes[i].click()
except Exception as e:
self.logger.debug(f"옵션 체크 조정 중 오류 발생: {str(e)}")
self.logger.error(f"옵션 체크 조정 중 오류 발생: {e}", exc_info=True)
def check_options(self, option_info):
"""옵션 체크 로직: 모든 옵션 체크 해제 후 다시 선택"""
@ -189,15 +229,15 @@ class OptionHandler:
self.logger.debug("모든 옵션 체크 해제 완료")
# 옵션 갯수에 따라 선택 로직 진행
total_options_count = len(option_info['original_names'])
total_options_count = len(self.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]
options_to_check = self.option_info['checkboxes'][1:self.max_selected_options + 1]
else:
# 2개 이하인 경우: 모두 체크
options_to_check = option_info['checkboxes']
options_to_check = self.option_info['checkboxes']
# 선택된 옵션들 체크
for checkbox in options_to_check:
@ -205,4 +245,17 @@ class OptionHandler:
self.logger.debug(f"옵션 체크 완료: {checkbox}")
except Exception as e:
self.logger.debug(f"옵션 체크 중 오류 발생: {str(e)}")
self.logger.error(f"옵션 체크 중 오류 발생: {e}", exc_info=True)
def low_order_click(self):
self.logger.debug("가격 낮은 순 정렬을 클릭합니다.")
self.page.click('button:has-text("가격 낮은 순")')
self.page.wait_for_load_state('domcontentloaded')
def save_option(self):
"""옵션 수정 후 저장 버튼 클릭"""
try:
self.page.click('button:has-text("저장하기")')
self.logger.debug("옵션 수정 내용 저장 완료.")
except Exception as e:
self.logger.debug(f"옵션수정 후 저장 버튼 클릭 중 오류: {e}", exc_info=True)

View File

@ -1,5 +1,5 @@
{
"option_prompt_template": "질문은 아래와 같아.\n\n가공방법\n1. 특수문자가 있을 경우 제거해줘.\n2. 원본 상품명을 참고해서, 각 옵션의 이름을 최대한 간결하게, 각 옵션의 특징만 남겨줘.\n3. 간결하게 만들어진 각 옵션명을 한국어로 일관되게 번역해줘.\n4. 번역된 옵션명들은 'trans_option_1': '', 'trans_option_2': '', 'trans_option_3': '', 'trans_option_4': '' 와 같은 형식(json)으로 반환해줘.\n\n원본 데이터\n{options}",
"option_prompt_template": "질문은 아래와 같아.\n\n가공방법\n1. 특수문자가 있을 경우 제거해줘.\n2. 원본 상품명을 참고해서, 각 옵션의 이름을 최대한 간결하게, 각 옵션의 특징만 남겨줘.\n3. 간결하게 만들어진 각 옵션명을 한국어로 일관되게 번역해줘.\n4. 각 옵션이름이 중복되면 안되.\n6. 가격문의, 문의사항, 견적, 견적문의, 예약금, 선결제, 고객센터 연락 등 옵션명을 바로 알려주지 않고 고객에게 연락을 유도하는 옵션명은 삭제해야 해.\n6. 번역된 옵션명들은 'trans_option_1': '', 'trans_option_2': '', 'trans_option_3': '', 'trans_option_4': '' 와 같은 형식(json)으로 반환해줘.\n\n원본 데이터\n{options}",
"detail_page_prompt_template": "상세 페이지 번역 요청: {detail_page}",
"title_prompt_template": "제목 번역 요청: {title}",
"price_prompt_template": "가격 가공 요청: {price}",

View File

@ -135,7 +135,7 @@ class PlaywrightTester(QWidget):
self.log_message(f"요소를 찾을 수 없음: {selector}")
except Exception as e:
self.log_message(f"오류 발생: {e}")
self.log_message(f"오류 발생: {e}", exc_info=True)
def find_element(self):
"""요소 찾기 동작"""
@ -185,7 +185,7 @@ class PlaywrightTester(QWidget):
self.log_message(f"요소 클릭 성공: {self.current_element_index + 1}/{len(self.elements)}")
except Exception as e:
self.log_message(f"클릭 오류 발생: {e}")
self.log_message(f"클릭 오류 발생: {e}", exc_info=True)
def click_element(self):
"""요소 클릭 동작"""

View File

@ -38,10 +38,10 @@ class VertexAITranslator:
self.logger.debug("prompt.json 파일이 성공적으로 로드되었습니다.")
return prompt_data
except FileNotFoundError as e:
self.logger.error(f"prompt.json 파일을 찾을 수 없습니다: {e}")
self.logger.error(f"prompt.json 파일을 찾을 수 없습니다: {e}", exc_info=True)
raise e
except json.JSONDecodeError as e:
self.logger.error(f"prompt.json 파일 파싱 중 오류 발생: {e}")
self.logger.error(f"prompt.json 파일 파싱 중 오류 발생: {e}", exc_info=True)
raise e
def clean_special_chars(self, text):
@ -106,8 +106,8 @@ class VertexAITranslator:
translated_data = json.loads(json_text)
self.logger.debug(f"번역된 데이터: {translated_data}")
except json.JSONDecodeError as e:
self.logger.error(f"응답 데이터를 파싱하는 중 오류 발생: {e}")
raise ValueError(f"응답 데이터를 파이썬의 딕셔너리로 파싱하는 중 오류 발생: {e}")
self.logger.error(f"응답 데이터를 파싱하는 중 오류 발생: {e}", exc_info=True)
raise ValueError(f"응답 데이터를 파이썬의 딕셔너리로 파싱하는 중 오류 발생: {e}", exc_info=True)
else:
self.logger.error("응답 데이터에서 유효한 JSON 형식을 찾을 수 없습니다.")
raise ValueError("응답 데이터에서 유효한 JSON 형식을 찾을 수 없습니다.")

View File

@ -87,7 +87,7 @@ class WhaleTranslator:
self.logger.debug("가상 데스크톱 2가 이미 존재합니다.")
except Exception as e:
self.logger.debug(f"가상 데스크톱 확인/생성 중 오류 발생: {e}")
self.logger.debug(f"가상 데스크톱 확인/생성 중 오류 발생: {e}", exc_info=True)
def switch_to_whale(self):
"""웨일로 포커스 전환"""
@ -106,7 +106,7 @@ class WhaleTranslator:
self.logger.debug("가상 데스크톱 2로 전환되었습니다.")
time.sleep(1)
except Exception as e:
self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}")
self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}", exc_info=True)
def return_to_virtual_desktop_1(self):
"""가상 데스크톱 1로 복귀"""
@ -115,7 +115,7 @@ class WhaleTranslator:
self.logger.debug("가상 데스크톱 1로 전환되었습니다.")
time.sleep(1)
except Exception as e:
self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}")
self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}", exc_info=True)
def translate_image(self, url):
if self.vd_mode:
@ -240,4 +240,4 @@ class WhaleTranslator:
self.logger.debug("모든 가상 데스크톱이 종료되었습니다.")
except Exception as e:
self.logger.debug(f"가상 데스크톱 종료 중 오류 발생: {e}")
self.logger.debug(f"가상 데스크톱 종료 중 오류 발생: {e}", exc_info=True)