diff --git a/browser_control.py b/browser_control.py
index 2426cccf..144ee1c3 100644
--- a/browser_control.py
+++ b/browser_control.py
@@ -267,31 +267,19 @@ class BrowserController:
def fetch_image_urls(self, html_content):
"""
- HTML 콘텐츠에서 모든
태그의 URL을 순서대로 추출하고 중복 제거.
+ HTML 콘텐츠에서 모든
태그의 URL을 HTML 소스의 순서대로 추출.
"""
soup = BeautifulSoup(html_content, 'html.parser')
- # 중복된 이미지를 제거하기 위해 set 사용
- image_urls_set = set()
-
- # class="image_resized"를 가진 모든
태그 찾기
- images_resized = soup.find_all('img', class_='image_resized')
- for img in images_resized:
+ # HTML 소스에서 순서대로
태그를 찾음
+ image_urls = []
+ img_tags = soup.find_all('img')
+ for img in img_tags:
if img and 'src' in img.attrs:
- image_urls_set.add(img['src']) # 중복을 방지하기 위해 set에 추가
+ image_urls.append(img['src']) # URL을 리스트에 추가
- # 내부의 모든
태그 찾기
- figures = soup.find_all('figure', class_='image')
- for figure in figures:
- img_tag = figure.find('img')
- if img_tag and 'src' in img_tag.attrs:
- image_urls_set.add(img_tag['src']) # 중복을 방지하기 위해 set에 추가
-
- # set을 list로 변환하여 반환 (순서 유지가 필요하면 set 대신 리스트로 처리해야 함)
- image_urls = list(image_urls_set)
return image_urls
-
async def close_ad_if_exists(self):
"""광고 다이얼로그가 있으면 닫기 버튼을 클릭하는 메서드"""
@@ -521,7 +509,8 @@ class BrowserController:
# 나머지 옵션들은 - 없이 숫자 접두사로 표시
for i, option in enumerate(option_data[1:], start=2):
option_text = option[0] if isinstance(option, tuple) else option
- option_prefix = f"{i}. "
+ # option_prefix = f"{i}. "
+ option_prefix = ""
await input_field.type(option_prefix + option_text)
await input_field.press('Enter') # 엔터 키를 입력하여 줄바꿈
@@ -545,12 +534,12 @@ class BrowserController:
self.logger.debug(f"이미지 URL 추출 중 오류: {e}", exc_info=True)
return []
- async def paste_image_in_chrome(self, clipboardImageManager, url):
+ def paste_image_in_chrome(self, clipboardImageManager, url):
"""크롬으로 포커스를 옮기고 클립보드의 이미지를 붙여넣고 엔터 입력"""
self.logger.debug("크롬으로 포커스를 옮기고 클립보드의 이미지를 붙여넣고 엔터 입력")
try:
self.switch_to_chrome() # 크롬으로 포커스 이동
- await clipboardImageManager.process_clipboard(url) # 클립보드 내용을 처리
+ clipboardImageManager.process_clipboard(url) # 클립보드 내용을 처리
# clipboard_content = pyperclip.paste()
if clipboardImageManager.is_clipboard_image():
pyautogui.hotkey('ctrl', 'v') # 클립보드 이미지 붙여넣기
diff --git a/clipboardImageManager.py b/clipboardImageManager.py
index 2e55b92a..15fbced1 100644
--- a/clipboardImageManager.py
+++ b/clipboardImageManager.py
@@ -179,16 +179,19 @@ class ClipboardImageManager:
else:
self.logger.debug(f"이미지 로딩 실패, HTTP 상태 코드: {response.status_code}. 재시도 {retries + 1}/{max_retries}")
retries += 1
- await asyncio.sleep(random.randint(2, 5)) # 2~5초 대기 후 재시도
+ # await asyncio.sleep(random.randint(2, 5)) # 2~5초 대기 후 재시도
+ time.sleep(random.randint(2, 5))
+
except Exception as e:
self.logger.debug(f"이미지 로딩 중 오류 발생: {e}. 재시도 {retries + 1}/{max_retries}")
retries += 1
- await asyncio.sleep(random.randint(2, 5)) # 예외 발생 시 대기 후 재시도
+ # await asyncio.sleep(random.randint(2, 5)) # 예외 발생 시 대기 후 재시도
+ time.sleep(random.randint(2, 5))
self.logger.debug("이미지 다운로드 최대 재시도 횟수를 초과했습니다.")
return None
- async def process_clipboard(self, original_url, path=None):
+ def process_clipboard(self, original_url, path=None):
"""클립보드의 내용을 처리하고, 필요한 경우 이미지 변환, 크롭 또는 클립보드 비우기"""
try:
@@ -248,7 +251,7 @@ class ClipboardImageManager:
self.logger.info("[process_clipboard] 클립보드에 이미지 없음")
if original_url:
- image = await self.download_image_from_url(original_url)
+ image = self.download_image_from_url(original_url)
if image:
self.logger.debug("원본 이미지 다운로드 성공, 클립보드에 저장 중...")
self.set_image_to_clipboard(image) # 크롭 없이 저장
diff --git a/gui.py b/gui.py
index 036dbdc2..5093d036 100644
--- a/gui.py
+++ b/gui.py
@@ -846,7 +846,7 @@ class TranslationApp(QWidget):
self.whale_translator.translate_image(url)
self.logger.debug(f"paste_image_in_chrome - 이미지 붙여넣기")
- await self.browser_controller.paste_image_in_chrome(self.clipboardImageManager, url)
+ self.browser_controller.paste_image_in_chrome(self.clipboardImageManager, url)
self.logger.debug(f"Progress Update")
self.update_detail_progress(i,total_images)
diff --git a/price.py b/price.py
index 3c6d3780..046463b2 100644
--- a/price.py
+++ b/price.py
@@ -27,6 +27,7 @@ class PriceHandler:
self.first_delv_fee = 0
self.exchange_fee = 0
self.sold_price = 0
+ self.initail_margin_cost = 0
# Locator들을 미리 로드하여 초기화 - locator_template:동적 로딩, locator:고정로딩
self.product_cost_locator_template = self.locator_manager.get_locator('PriceLocators', 'product_cost_locator')
@@ -331,6 +332,10 @@ class PriceHandler:
- adjusted_margin (int): 적정 판매가에 맞게 조정된 더하기 마진.
"""
try:
+ if not option_data or len(option_data) == 0:
+ self.logger.warning(f"옵션 데이터가 없거나 비어있습니다. 계산원가 기준 더하기마진({self.initail_margin_cost}) 을 반환합니다.")
+ return self.initail_margin_cost # 기본 더하기 마진 설정
+
total_option_price = math.ceil(sum([option['price'] for option in option_data]) / len(option_data))
self.logger.debug(f"총 옵션 기준 판매가 평균: {total_option_price}")
@@ -503,11 +508,11 @@ class PriceHandler:
initail_shipping_cost = self.round_to_UP(initail_shipping_cost)
self.logger.debug(f"계산원가 기준 해외배송비: {initail_shipping_cost}")
- initail_margin_cost = self.calculate_shipping_cost_with_extended_thresholds(10000, initial_cost_price)
- initail_margin_cost = self.round_to_UP(initail_margin_cost)
- self.logger.debug(f"계산원가 기준 더하기마진: {initail_margin_cost}")
+ self.initail_margin_cost = self.calculate_shipping_cost_with_extended_thresholds(10000, initial_cost_price)
+ self.initail_margin_cost = self.round_to_UP(self.initail_margin_cost)
+ self.logger.debug(f"계산원가 기준 더하기마진: {self.initail_margin_cost}")
- result = int(initial_cost_price + initail_shipping_cost + initail_margin_cost)
+ result = int(initial_cost_price + initail_shipping_cost + self.initail_margin_cost)
self.logger.debug(f"원가기반 가격: {result}")
return result
diff --git a/src/img/translating.png b/src/img/translating.png
new file mode 100644
index 00000000..a24d4fbe
Binary files /dev/null and b/src/img/translating.png differ
diff --git a/test/img_test.py b/test/img_test.py
index 7d574fbb..6673c3a5 100644
--- a/test/img_test.py
+++ b/test/img_test.py
@@ -3,12 +3,17 @@ import time
import os
import subprocess
import win32gui, win32con, win32process
+import pyscreeze
class WhaleTranslator:
def __init__(self, logger, error_image_filenames=['fail_translated1.png', 'fail_translated2.png'], pixel_check_interval=0.1, secret_mode=True, timeout=20, color_tolerance=20):
self.logger = logger
self.error_image_paths = [os.path.join(os.path.dirname(__file__), filename) for filename in error_image_filenames]
+
self.page_loading_icon_path = os.path.join(os.path.dirname(__file__), 'page_loading.png')
+ self.translating_image_path = os.path.join(os.path.dirname(__file__), 'translating.png')
+ # self.translating_image_path = os.path.join(os.path.dirname(__file__), 'src', 'img', 'translating.png')
+
self.pixel_check_interval = pixel_check_interval
self.whale_window_name = "새 시크릿 탭 - Whale" if secret_mode else "새 탭 - Whale"
@@ -16,6 +21,7 @@ class WhaleTranslator:
self.timeout = timeout # 번역 성공 여부를 판단하기 위한 시간 제한 설정
self.color_tolerance = color_tolerance # 색상 허용 오차
self.colors = {'before': None, 'during': None, 'after': None} # 색상 기록
+ self.whale_rect = None
def start_whale_browser(self, url):
whale_path = r"C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe"
@@ -26,8 +32,9 @@ class WhaleTranslator:
hwnd = self.find_whale_window()
if hwnd:
- self.set_window_position(hwnd, 100, 100, 1280, 720) # 위치 (100, 100), 크기 (1280x720)
-
+ self.set_window_position(hwnd, 1, 1, 1280, 720) # 위치 (100, 100), 크기 (1280x720)
+ self.update_whale_rect()
+
if hwnd:
win32gui.SetForegroundWindow(hwnd)
pyautogui.hotkey('ctrl', 'l')
@@ -36,10 +43,10 @@ class WhaleTranslator:
pyautogui.press('enter')
time.sleep(2)
- # 페이지 로딩 완료 대기
- self.wait_for_loading_icon_to_disappear()
+ # # 페이지 로딩 완료 대기
+ # self.wait_for_loading_icon_to_disappear()
- self.move_mouse_to_center(hwnd) # 마우스 중앙으로 이동
+ self.move_mouse_to_center() # 마우스 중앙으로 이동
time.sleep(0.5) # 마우스 이동 후 대기
original_color = self.get_mouse_position_color() # 현재 색상 가져오기
@@ -50,21 +57,24 @@ class WhaleTranslator:
pyautogui.rightClick()
time.sleep(1)
pyautogui.press('r')
- time.sleep(1)
- # 번역 성공 여부 확인
- result = self.check_translation_by_color_change(original_color)
- if result == "success":
- print("번역이 성공적으로 완료되었습니다!")
- elif result == "error":
- print("번역에 실패했습니다.")
- else:
- print("번역 상태를 확인하지 못했습니다.")
+ # 번역 시작 감지 (translating.png 확인)
+ if self.is_translating():
+ self.logger.debug("번역 시작 감지 ('translating.png' 발견)")
+
+ # 번역 중 색상 지속 확인
+ result = self.check_translation_by_color_change()
+
+ if result == "success":
+ self.logger.debug(f"URL: {url} - 번역이 성공적으로 완료되었습니다!")
+ elif result == "error":
+ self.logger.debug(f"URL: {url} - 번역에 실패했습니다.")
+ else:
+ self.logger.debug(f"URL: {url} - 번역 상태를 확인하지 못했습니다.")
# 최종 색상 출력
- self.logger.debug(f"번역 전 색상: {self.colors['before']}")
- self.logger.debug(f"번역 중 색상: {self.colors['during']}")
- self.logger.debug(f"번역 후 색상: {self.colors['after']}")
+ self.logger.debug(f"URL: {url} - 번역 중 색상: {self.colors['during']}")
+ self.logger.debug(f"URL: {url} - 번역 후 색상: {self.colors['after']}")
def wait_for_loading_icon_to_disappear(self, max_wait=20):
"""
@@ -75,19 +85,65 @@ class WhaleTranslator:
while time.time() - start_time < max_wait:
try:
# 화면에서 아이콘 위치 확인 시도
- icon_location = pyautogui.locateOnScreen(self.page_loading_icon_path, confidence=0.9)
+ icon_location = self.find_image_with_confidence(self.page_loading_icon_path, confidence=0.9)
if icon_location:
- print("페이지 로딩 중...")
+ self.logger.debug("페이지 로딩 중...")
time.sleep(0.5) # 간격을 두고 다시 확인
- except pyautogui.ImageNotFoundException:
+ except pyautogui.ImageNotFoundException as e:
# 아이콘이 화면에 없으면 로딩 완료로 간주
- print("페이지 로딩이 완료되었습니다.")
+ # self.logger.debug(f"페이지 로딩이 완료되었습니다. {e}", exc_info=True)
+ self.logger.debug(f"페이지 로딩이 완료되었습니다.")
return True # 로딩 완료
- print("로딩 완료 대기 시간이 초과되었습니다.")
+ self.logger.debug("로딩 완료 대기 시간이 초과되었습니다.")
return False
+ def find_image_with_confidence(self, image_path, confidence=0.8):
+ """이미지를 찾을 때 highest confidence 값을 로그로 출력하는 메서드"""
+ if self.whale_rect:
+
+ # 웨일 창의 크기를 region으로 설정
+ region = (self.whale_rect[0], self.whale_rect[1],
+ self.whale_rect[2] - self.whale_rect[0],
+ self.whale_rect[3] - self.whale_rect[1])
+ self.logger.debug(f"이미지를 찾을 영역: {region}")
+
+ try:
+ # locateOnScreen 시도
+ result = pyscreeze.locateOnScreen(image_path, confidence=confidence, region=region)
+
+ if result:
+ self.logger.debug(f"이미지를 찾았습니다: {image_path}")
+ return result
+ else:
+ raise pyscreeze.ImageNotFoundException("Could not locate the image")
+
+ except pyscreeze.ImageNotFoundException as e:
+ # 'Could not locate the image' 메시지 발생 시 최고 confidence 값 로그 출력
+ if hasattr(e, 'args') and 'highest confidence' in str(e.args[0]):
+ self.logger.error(f"이미지를 찾지 못했습니다만 유사한 부분을 찾았습니다. : [{e.args[0]}]")
+ else:
+ self.logger.error("이미지를 찾지 못했습니다. 이미지와 유사한 부분을 찾지 못했습니다.")
+ return None
+
+ def is_translating(self):
+ """translating.png가 화면에 나타나는지 확인하여 번역 시작 여부를 판단"""
+ try:
+ # translating_location = pyautogui.locateOnScreen(self.translating_image_path, confidence=0.8)
+ translating_location = self.find_image_with_confidence(self.translating_image_path, confidence=0.8)
+ if translating_location:
+ return True
+ except pyautogui.ImageNotFoundException as e:
+ self.logger.debug(f"'translating.png'를 찾지 못했습니다. : {e}", exc_info=True)
+ return False
+
+ def update_whale_rect(self):
+ """웨일 창의 위치 및 크기 rect를 업데이트"""
+ if self.whale_hwnd:
+ self.whale_rect = win32gui.GetWindowRect(self.whale_hwnd)
+ self.logger.debug(f"웨일 창 크기 및 위치 저장: {self.whale_rect}")
+
def find_whale_window(self):
"""웨일 창을 제목을 기준으로 찾는 메서드"""
def callback(hwnd, extra):
@@ -99,8 +155,10 @@ class WhaleTranslator:
hwnd_list = []
win32gui.EnumWindows(callback, hwnd_list)
if hwnd_list:
- self.logger.debug(f"웨일 창을 찾았습니다: {hwnd_list[0]}")
- return hwnd_list[0]
+ self.whale_hwnd = hwnd_list[0]
+ self.logger.debug(f"웨일 창을 찾았습니다: {self.whale_hwnd}")
+ self.update_whale_rect()
+ return self.whale_hwnd
else:
self.logger.debug("웨일 창을 찾지 못했습니다.")
return None
@@ -111,40 +169,60 @@ class WhaleTranslator:
win32gui.SetWindowPos(hwnd, None, x, y, width, height, win32con.SWP_NOZORDER | win32con.SWP_NOACTIVATE)
self.logger.debug(f"창 위치 및 크기 설정: 위치({x}, {y}), 크기({width}x{height})")
- def move_mouse_to_center(self, hwnd):
+ def move_mouse_to_center(self):
"""웨일 브라우저 창의 중앙으로 마우스 커서를 이동"""
- rect = win32gui.GetWindowRect(hwnd) # 창 위치 및 크기 가져오기
- center_x = (rect[0] + rect[2]) // 2 # 가로 중앙 계산
- center_y = (rect[1] + rect[3]) // 2 # 세로 중앙 계산
- pyautogui.moveTo(center_x, center_y)
- self.logger.debug(f"마우스 커서를 창 중앙으로 이동: ({center_x}, {center_y})")
+ if self.whale_rect:
+ center_x = (self.whale_rect[0] + self.whale_rect[2]) // 2 # 가로 중앙 계산
+ center_y = (self.whale_rect[1] + self.whale_rect[3]) // 2 # 세로 중앙 계산
+ pyautogui.moveTo(center_x, center_y)
+ self.logger.debug(f"마우스 커서를 창 중앙으로 이동: ({center_x}, {center_y})")
+ else:
+ self.logger.error("웨일 창의 크기를 알 수 없습니다. 먼저 창을 찾으세요.")
- def check_translation_by_color_change(self, original_color):
+ def is_color_changed(self, current_color):
+ """현재 색상이 변화했는지 확인 (필터 제거 여부)"""
+ if self.colors['during'] is None:
+ self.colors['during'] = current_color
+ return not self.is_similar_color(current_color, self.colors['during'])
+
+
+
+ def check_translation_by_color_change(self):
start_time = time.time()
+
+ # 번역 시작 감지 (translating.png 확인)
while time.time() - start_time < self.timeout:
current_color = self.get_mouse_position_color()
- if self.colors['during'] is None: # 번역 중 첫 색상 기록
- self.colors['during'] = current_color
self.logger.debug(f"현재 색상: {current_color}")
- if self.is_similar_color(current_color, original_color):
+ # 필터가 사라져서 색상이 변했는지 확인
+ if self.is_color_changed(current_color):
self.colors['after'] = current_color
- self.logger.debug("번역 성공 감지 (원래 색상과 유사)")
- return "success"
-
- if not self.is_similar_color(current_color, original_color):
- self.logger.debug("번역 중 상태 감지 (필터 색상)")
-
+ self.logger.debug("색상 변화 감지 (필터 제거됨)")
+
+ # translating.png가 여전히 존재하는지 확인하여 번역 성공 여부 판단
+ result = self.find_image_with_confidence(self.translating_image_path, confidence=0.8)
+ if result:
+ return "success"
+ else:
+ return "error"
+ else:
+ # 번역 실패 이미지 확인
if self.is_translation_failed():
self.colors['after'] = current_color
return "error"
time.sleep(self.pixel_check_interval)
-
- # 타임아웃 발생 시, 번역 성공으로 간주
+
+ # 타임아웃 발생 시 translating.png 여부로 번역 성공/실패 판단
self.colors['after'] = current_color
- self.logger.debug("번역 성공으로 간주 (타임아웃)")
- return "success"
+ result = self.find_image_with_confidence(self.translating_image_path, confidence=0.8)
+ if result:
+ self.logger.debug("번역 성공으로 간주 (타임아웃 후 translating.png 존재)")
+ return "success"
+ else:
+ self.logger.debug("번역 실패로 간주 (타임아웃 후 translating.png 없음)")
+ return "error"
def is_similar_color(self, color1, color2):
"""색상이 유사한지 확인 (허용 오차 적용)"""
@@ -160,12 +238,10 @@ class WhaleTranslator:
def is_translation_failed(self):
"""번역 실패 이미지 확인"""
for image_path in self.error_image_paths:
- try:
- if pyautogui.locateOnScreen(image_path, confidence=0.8):
- self.logger.error(f"번역 실패: '{os.path.basename(image_path)}' 메시지가 감지되었습니다.")
- return True
- except pyautogui.ImageNotFoundException:
- self.logger.debug(f"번역 실패 이미지가 화면에 없습니다: {os.path.basename(image_path)}")
+ result = self.find_image_with_confidence(image_path, confidence=0.8)
+ if result:
+ self.logger.error(f"번역 실패: '{os.path.basename(image_path)}' 메시지가 감지되었습니다.")
+ return True
return False
# 예제 사용법
@@ -179,4 +255,7 @@ logger = logging.getLogger(__name__)
translator = WhaleTranslator(logger, ['fail_translated1.png', 'fail_translated2.png'])
# 브라우저 실행 후 URL로 이동 및 번역 성공 여부 확인
-translator.start_whale_browser("https://file.percenty.co.kr/public/652bed8e865b1f32ea62bf1f/products/66ff967773994c46d388bb36/82d07178-ae60-49f7-a489-e02801ff7b06.jpg")
+# translator.start_whale_browser("https://file.percenty.co.kr/public/652bed8e865b1f32ea62bf1f/products/66ff967773994c46d388bb36/82d07178-ae60-49f7-a489-e02801ff7b06.jpg")
+translator.start_whale_browser('https://img.alicdn.com/imgextra/i4/735691568/O1CN01sRUYqb1NSBuefMBlw_!!735691568.jpg_Q75.jpg')
+translator.start_whale_browser('https://img.alicdn.com/imgextra/i4/1773313923/O1CN01VMRs1Z1eqmfYSXQDu_!!1773313923.jpg_Q75.jpg')
+
diff --git a/test/page_loading_2.png b/test/page_loading_2.png
new file mode 100644
index 00000000..0bcca4b1
Binary files /dev/null and b/test/page_loading_2.png differ
diff --git a/test/translating.png b/test/translating.png
new file mode 100644
index 00000000..f3f7aa8c
Binary files /dev/null and b/test/translating.png differ
diff --git a/whale_translator.py b/whale_translator.py
index 40be90eb..4ca454dc 100644
--- a/whale_translator.py
+++ b/whale_translator.py
@@ -32,7 +32,7 @@ class WhaleTranslator:
self.page_loading_icon_path = os.path.join(img_dir, 'page_loading.png')
self.translation_success_flag = False # 번역 성공 플래그
- # self.failure_count = 0 # 실패 횟수
+ self.failure_count = 0 # 실패 횟수
if isSecret:
self.whale_window_name = "새 시크릿 탭 - Whale"
@@ -89,10 +89,10 @@ class WhaleTranslator:
if self.vd_mode:
self.return_to_virtual_desktop_1() # 가상 데스크탑 1로 복귀
- # def reset_failures(self):
- # """실패 횟수를 초기화"""
- # self.failure_count = 0
- # self.logger.debug("실패 횟수가 초기화되었습니다.")
+ def reset_failures(self):
+ """실패 횟수를 초기화"""
+ self.failure_count = 0
+ self.logger.debug("실패 횟수가 초기화되었습니다.")
# def handle_translation_failure(self):
# """번역 실패 시 처리"""