로컬변경
This commit is contained in:
commit
25b6e7ba63
|
|
@ -5,7 +5,7 @@ from selenium.webdriver.chrome.service import Service
|
|||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from tqdm import tqdm
|
||||
# from tqdm import tqdm
|
||||
from selenium_stealth import stealth
|
||||
from fake_useragent import UserAgent
|
||||
import random
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from playwright.sync_api import sync_playwright
|
||||
<<<<<<< HEAD
|
||||
import random
|
||||
import logging
|
||||
|
||||
|
|
@ -72,3 +73,5 @@ def trans_text(original_text):
|
|||
logger.info("playwright Browser 닫힘.")
|
||||
|
||||
return translated_text
|
||||
=======
|
||||
>>>>>>> 4b4ff58484a1cc6a2080061367ea02ec8d38e8b7
|
||||
|
|
|
|||
|
|
@ -55,7 +55,10 @@ class ImageDescriptionGenerator:
|
|||
self.fill_product_info_lists(product_info)
|
||||
|
||||
prompt = f'''
|
||||
주어진 상품 이미지에 대한 정보를 줄께.
|
||||
나는 타오바오에서 상품을 가져와서 한국의 온라인 쇼핑몰에서 구매대행업을 하는 사업가야.
|
||||
너는 온라인 쇼핑몰 상세페이지 제작 전문가야. 니가 만든 상품페이지는 모두를 감동시키고, 구매로 이어지는 마법같은 능력이 있어.
|
||||
이제 주어진 이미지와 내가 원하는 상세페이지에 대한 정보를 줄께.
|
||||
하나씩 차근차근 진행해보자.
|
||||
[정보]
|
||||
A. 해당상품의 타오바오 상품명은 '{product_info.tao_title}'
|
||||
B. 해당상품의 키워드는 '{product_info.keyword_title}'
|
||||
|
|
@ -79,7 +82,7 @@ class ImageDescriptionGenerator:
|
|||
4. 이 상품의 사용상 주의점을 자세히 알려줘
|
||||
5. 이 상품의 도움이 될만한 또 다른 추가정보를 자세하게 알려줘
|
||||
|
||||
|
||||
|
||||
6. 위의 모든 정보를 바탕으로 상품을 잘 설명한 상품명을 만들어줘 1개 만들어줘.
|
||||
6-1. 상품명 제작 권장 사항 1: 키워드, 용도, 재질, 용량, 형식, 모양,특징등의 단어를 콤마를 제외하고 띄어쓰기로 나열해(용량과 스펙등은 뒤쪽으로 배치).
|
||||
6-2. 상품명 제작 권장 사항 2: 타오바오 상품명과 옵션이름들에서 상품의 특징을 가져와서 상품명에 사용해야해.
|
||||
|
|
|
|||
|
|
@ -151,10 +151,11 @@ class AutoPercentyProductsDB:
|
|||
'tag_modification': 'complete',
|
||||
'option_modification': 'complete',
|
||||
'detail_page_modification': 'complete',
|
||||
'thumbnail_modification': 'complete'
|
||||
# 'thumbnail_modification': 'complete',
|
||||
'thumbnail_modification': 'complete',
|
||||
# 'price_modification': 'complete',
|
||||
# 'title_modification': 'complete'
|
||||
# 'title_modification': 'complete',
|
||||
# 'trans_detailImage': 'complete',
|
||||
# 'upload_to_market': 'complete',
|
||||
}
|
||||
|
||||
# 현재 시간
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ def create_product_card(product_name, image_url, price, rank, purchase, review):
|
|||
|
||||
# return product_info_md
|
||||
|
||||
def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes):
|
||||
def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes, login_info):
|
||||
|
||||
detail_css = ".ant-tabs-tab:nth-child(6)"
|
||||
|
||||
|
|
@ -625,27 +625,33 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver
|
|||
logger.error(f"AI 컨텐츠 입력 중 에러발생 : {e}", exc_info=True)
|
||||
|
||||
|
||||
# logger.debug("상세페이지 이미지 번역 시작")
|
||||
# try:
|
||||
# for i, detail_image in enumerate(detail_images):
|
||||
# logger.debug(f"상세페이지 {i+1}번째 이미지 번역 시작")
|
||||
# logger.debug(f"이미지 타입 : {type(detail_image)}")
|
||||
# returned_img = image_trans(detail_image, 'translate')
|
||||
# image_to_clipboard(returned_img)
|
||||
# logger.debug("번역 완료 및 부텨넣기")
|
||||
# detail_content.send_keys(Keys.CONTROL, 'v')
|
||||
# detail_content.send_keys(Keys.ENTER)
|
||||
|
||||
# logger.debug(f"{i}번째 이미지 붙여넣기 완료")
|
||||
|
||||
# # translated_image_urls.append(returned_img_path)
|
||||
|
||||
# logger.debug("이미지 번역 완료")
|
||||
# except Exception as e:
|
||||
# logger.error(f"이미지 번역 중 에러발생 : {e}", exc_info=True)
|
||||
|
||||
|
||||
if login_info.whether_modifyImageTanslation:
|
||||
logger.debug("상세페이지 이미지 번역 시작")
|
||||
try:
|
||||
for i, detail_image in enumerate(detail_images):
|
||||
logger.debug(f"상세페이지 {i+1}번째 이미지 번역 시작")
|
||||
logger.debug(f"이미지 타입 : {type(detail_image)}")
|
||||
returned_img = image_trans(detail_image, 'translate')
|
||||
image_to_clipboard(returned_img)
|
||||
logger.debug("번역 완료 및 부텨넣기")
|
||||
detail_content.send_keys(Keys.CONTROL, 'v')
|
||||
detail_content.send_keys(Keys.ENTER)
|
||||
|
||||
logger.debug(f"{i}번째 이미지 붙여넣기 완료")
|
||||
|
||||
# translated_image_urls.append(returned_img_path)
|
||||
|
||||
logger.debug("이미지 번역 완료")
|
||||
except Exception as e:
|
||||
logger.error(f"이미지 번역 중 에러발생 : {e}", exc_info=True)
|
||||
|
||||
|
||||
# logger.debug("====번역이미지 붙여넣기 완료=====")
|
||||
logger.debug("====번역이미지 붙여넣기 완료=====")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
logger.debug("상세페이지 편집 저장")
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
import time, re, random
|
||||
from edit.action_elements import click_element, return_element, click_and_confirm_tab
|
||||
from edit.price_cal import calculate_margin_and_price
|
||||
|
||||
# from ai.compare import find_most_similar_image_by_one
|
||||
import logging
|
||||
|
||||
# 로거 인스턴스 가져오기
|
||||
logger = logging.getLogger('default_logger')
|
||||
|
||||
def tran_detail_image(driver, product_infos):
|
||||
return None
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
import time, re, random
|
||||
from edit.action_elements import click_element, return_element, click_and_confirm_tab
|
||||
from edit.price_cal import calculate_margin_and_price
|
||||
|
||||
# from ai.compare import find_most_similar_image_by_one
|
||||
import logging
|
||||
|
||||
# 로거 인스턴스 가져오기
|
||||
logger = logging.getLogger('default_logger')
|
||||
|
||||
def upload_to_market(driver, product_infos):
|
||||
return None
|
||||
|
|
@ -8,6 +8,7 @@ import numpy as np
|
|||
from img_trans.src.text_detection_with_paddle import detect_text
|
||||
from img_trans.src.removal import process_image_based_on_text_area
|
||||
from img_trans.src.translation import translate_texts_translatepy
|
||||
from img_trans.src.translation import translate_texts_deepl
|
||||
from img_trans.src.text_insertion import insert_text
|
||||
from img_trans.src.mini_crop_process import resize_and_crop_image
|
||||
from img_trans.src.rotate_img import flip_and_rotate_image
|
||||
|
|
@ -68,6 +69,8 @@ def image_trans(image_url, convert_type):
|
|||
texts_to_translate = [text for _, text, _, _, _ in detected_texts]
|
||||
logger.debug(f"원본 텍스트: {texts_to_translate}")
|
||||
translated_texts = translate_texts_translatepy(texts_to_translate)
|
||||
if not translated_texts: # 빈 리스트 체크
|
||||
translated_texts = translate_texts_translatepy(texts_to_translate)
|
||||
logger.debug(f"번역 텍스트: {texts_to_translate}")
|
||||
# translated_image = insert_text(inpainted_image_path, translated_texts, detected_texts)
|
||||
translated_image = insert_text(inpainted_image, translated_texts, detected_texts)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
from googletrans import Translator
|
||||
from img_trans.src.deepl import trans
|
||||
# from img_trans.src.deepl_ori import trans
|
||||
from ai.deepl import trans
|
||||
from translatepy import Translator
|
||||
import logging
|
||||
|
||||
# 로거 인스턴스 가져오기
|
||||
logger = logging.getLogger('default_logger')
|
||||
|
||||
def translate_texts_google(texts, src_lang='zh-cn', dest_lang='ko'):
|
||||
"""텍스트 리스트를 지정된 언어에서 다른 언어로 번역"""
|
||||
translated_texts = []
|
||||
translator = Translator()
|
||||
print(f"texts ======== {texts}")
|
||||
print(f"texts number ======== {len(texts)}")
|
||||
logger.debug(f"texts ======== {texts}")
|
||||
logger.debug(f"texts number ======== {len(texts)}")
|
||||
try:
|
||||
translations = translator.translate(texts, src=src_lang, dest=dest_lang)
|
||||
translated_texts = [translation.text for translation in translations]
|
||||
except AttributeError as e:
|
||||
print(f"번역 실패: Google 번역 API의 내부 변경으로 인해 번역을 수행할 수 없습니다. : {e}")
|
||||
logger.error(f"번역 실패: Google 번역 API의 내부 변경으로 인해 번역을 수행할 수 없습니다. : {e}")
|
||||
return translated_texts
|
||||
|
||||
|
||||
|
|
@ -20,7 +25,8 @@ def translate_texts_deepl(texts):
|
|||
"""텍스트 리스트를 지정된 언어에서 다른 언어로 번역"""
|
||||
# 텍스트 리스트를 엔터로 구분된 하나의 문자열로 합침
|
||||
combined_text = "\n".join(texts)
|
||||
|
||||
translated_texts = []
|
||||
|
||||
# DeepL로 전체 텍스트 번역
|
||||
try:
|
||||
translated_combined_text = trans(combined_text)
|
||||
|
|
@ -30,7 +36,7 @@ def translate_texts_deepl(texts):
|
|||
# 번역된 전체 텍스트를 엔터를 기준으로 분리하여 리스트로 만듦
|
||||
translated_texts = translated_combined_text.split("\n")
|
||||
except AttributeError as e:
|
||||
print(f"번역 실패: {e}")
|
||||
logger.error(f"번역 실패: {e}")
|
||||
translated_texts = []
|
||||
|
||||
return translated_texts
|
||||
|
|
@ -40,8 +46,8 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
|
|||
"""translatepy 라이브러리를 사용하여 텍스트 리스트를 번역합니다."""
|
||||
translator = Translator()
|
||||
translated_texts = []
|
||||
print(f"번역대상 텍스트 숫자 ======== {len(texts)}")
|
||||
print(f"번역대상 텍스트 ======== {texts}")
|
||||
logger.debug(f"번역대상 텍스트 숫자 ======== {len(texts)}")
|
||||
logger.debug(f"번역대상 텍스트 ======== {texts}")
|
||||
|
||||
for text in texts:
|
||||
result = translator.translate(text, source_language=src_lang, destination_language=dest_lang)
|
||||
|
|
@ -49,7 +55,7 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
|
|||
# "가격"이 포함된 경우 빈 문자열로 대체
|
||||
translated_texts.append(translation if "가격" not in translation else "")
|
||||
|
||||
print(f"번역된 감지 텍스트 \n {translated_texts}")
|
||||
logger.debug(f"번역된 감지 텍스트 \n {translated_texts}")
|
||||
|
||||
return translated_texts
|
||||
|
||||
|
|
@ -57,8 +63,8 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
|
|||
# texts = ["Hello, world!", "This is a test translation."]
|
||||
# translated_texts = translate_texts_translatepy(texts, src_lang='en', dest_lang='ko')
|
||||
# for text, translated in zip(texts, translated_texts):
|
||||
# print(f'{text} => {translated}')
|
||||
# logger.debug(f'{text} => {translated}')
|
||||
|
||||
# text='老顾客多次回购'
|
||||
# trans_ted = translate_texts_deepl(text)
|
||||
# print(f"trans_ted : {trans_ted}")
|
||||
# logger.debug(f"trans_ted : {trans_ted}")
|
||||
246
login_widget.py
246
login_widget.py
|
|
@ -3,6 +3,8 @@ from PyQt5.QtCore import Qt, QSettings
|
|||
from PyQt5 import QtWidgets, QtCore, QtWidgets
|
||||
from datetime import datetime
|
||||
from credentials import load_credentials, save_credentials
|
||||
from src.toggleSwitch import ToggleSwitch # toggle_switch.py에서 ToggleSwitch 클래스를 import
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
|
@ -30,14 +32,43 @@ class LoginWidget(QtWidgets.QWidget):
|
|||
self.per_mode = False
|
||||
self.set_num_modify = 0
|
||||
|
||||
self.alwaysOnTopSwitch = True
|
||||
self.whether_shutdownAfterComplete = False
|
||||
self.whether_modifyProductName = False
|
||||
self.whether_modifyProductOptions = True
|
||||
self.whether_modifyProductTag = True
|
||||
self.whether_modifyProductPrice = False
|
||||
self.whether_modifyProductThumb = True
|
||||
self.whether_modifyProductDetail = True
|
||||
self.whether_modifyImageTanslation = False
|
||||
self.whether_uploadToMarket = False
|
||||
|
||||
|
||||
self.check_for_updates(self.login_db, self.CURRENT_VERSION)
|
||||
|
||||
|
||||
def initUI(self):
|
||||
self.setGeometry(780, 420, 240, 200)
|
||||
# self.setGeometry(780, 420, 240, 200)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
# 위젯의 크기를 설정합니다.
|
||||
self.resize(800, 800)
|
||||
self.center() # 화면 가운데에 위치시키는 메서드
|
||||
|
||||
# 레이아웃 설정
|
||||
layout = QtWidgets.QHBoxLayout()
|
||||
|
||||
login_info_frame = QtWidgets.QFrame()
|
||||
login_layout = QtWidgets.QVBoxLayout()
|
||||
login_info_frame.setLayout(login_layout)
|
||||
|
||||
# 선택사항 영역
|
||||
setting_frame = QtWidgets.QFrame()
|
||||
setting_layout = QtWidgets.QVBoxLayout()
|
||||
setting_frame.setLayout(setting_layout)
|
||||
|
||||
# 레이아웃 설정
|
||||
layout.addWidget(login_info_frame)
|
||||
layout.addWidget(setting_frame)
|
||||
|
||||
self.signupButton = QtWidgets.QPushButton("회원 가입")
|
||||
self.signupButton.clicked.connect(self.showSignUpWindow)
|
||||
|
|
@ -76,7 +107,7 @@ class LoginWidget(QtWidgets.QWidget):
|
|||
self.infoLabel3 = QtWidgets.QLabel("=====================================")
|
||||
|
||||
# 토글 버튼 추가
|
||||
self.changeModeButton = QtWidgets.QPushButton("관리자용용모드")
|
||||
self.changeModeButton = QtWidgets.QPushButton("관리자용 모드")
|
||||
self.changeModeButton.setCheckable(True)
|
||||
self.changeModeButton.clicked.connect(self.toggleMode)
|
||||
# 초기 토글 상태 설정
|
||||
|
|
@ -94,27 +125,204 @@ class LoginWidget(QtWidgets.QWidget):
|
|||
self.loginButton = QtWidgets.QPushButton("로그인")
|
||||
self.loginButton.clicked.connect(self.login)
|
||||
|
||||
self.alwaysOnTopSwitch = ToggleSwitch(self)
|
||||
self.alwaysOnTopSwitch.move(10, 10)
|
||||
self.alwaysOnTopSwitch.setChecked(True) # 기본 상태는 ON
|
||||
self.alwaysOnTopSwitch.clicked.connect(self.toggleAlwaysOnTop)
|
||||
self.alwaysOnTopSwitch_layout = self.create_label_and_switch("항상 위에 표시", self.alwaysOnTopSwitch)
|
||||
|
||||
self.shutdownSwitch = ToggleSwitch(self)
|
||||
self.shutdownSwitch.move(10, 50)
|
||||
self.shutdownSwitch.setChecked(False) # 기본 상태는 OFF
|
||||
self.shutdownSwitch.clicked.connect(self.shutdownAfterComplete)
|
||||
self.shutdownSwitch_layout = self.create_label_and_switch("작업 종료 후 PC 종료", self.shutdownSwitch)
|
||||
|
||||
|
||||
self.modifyProductNameSwitch = ToggleSwitch(self)
|
||||
self.modifyProductNameSwitch.move(10, 90)
|
||||
self.modifyProductNameSwitch.setChecked(False) # 기본 상태는 OFF
|
||||
self.modifyProductNameSwitch.clicked.connect(self.modifyProductName)
|
||||
self.modifyProductNameSwitch_layout = self.create_label_and_switch("상품명 수정", self.modifyProductNameSwitch)
|
||||
|
||||
|
||||
self.modifyProductOptionsSwitch = ToggleSwitch(self)
|
||||
self.modifyProductOptionsSwitch.move(10, 90)
|
||||
self.modifyProductOptionsSwitch.setChecked(True) # 기본 상태는 OFF
|
||||
self.modifyProductOptionsSwitch.clicked.connect(self.modifyProductOptions)
|
||||
self.modifyProductOptionsSwitch_layout = self.create_label_and_switch("옵션명 수정", self.modifyProductOptionsSwitch)
|
||||
|
||||
|
||||
self.modifyProductTagSwitch = ToggleSwitch(self)
|
||||
self.modifyProductTagSwitch.move(10, 90)
|
||||
self.modifyProductTagSwitch.setChecked(True) # 기본 상태는 OFF
|
||||
self.modifyProductTagSwitch.clicked.connect(self.modifyProductTag)
|
||||
self.modifyProductTagSwitch_layout = self.create_label_and_switch("태그 수정", self.modifyProductTagSwitch)
|
||||
|
||||
|
||||
self.modifyProductPriceSwitch = ToggleSwitch(self)
|
||||
self.modifyProductPriceSwitch.move(10, 90)
|
||||
self.modifyProductPriceSwitch.setChecked(False) # 기본 상태는 OFF
|
||||
self.modifyProductPriceSwitch.clicked.connect(self.modifyProductPrice)
|
||||
self.modifyProductPriceSwitch_layout = self.create_label_and_switch("가격 수정", self.modifyProductPriceSwitch)
|
||||
|
||||
|
||||
self.modifyProductThumbSwitch = ToggleSwitch(self)
|
||||
self.modifyProductThumbSwitch.move(10, 90)
|
||||
self.modifyProductThumbSwitch.setChecked(True) # 기본 상태는 OFF
|
||||
self.modifyProductThumbSwitch.clicked.connect(self.modifyProductThumb)
|
||||
self.modifyProductThumbSwitch_layout = self.create_label_and_switch("썸네일 수정", self.modifyProductThumbSwitch)
|
||||
|
||||
|
||||
self.modifyProductDetailSwitch = ToggleSwitch(self)
|
||||
self.modifyProductDetailSwitch.move(10, 90)
|
||||
self.modifyProductDetailSwitch.setChecked(True) # 기본 상태는 OFF
|
||||
self.modifyProductDetailSwitch.clicked.connect(self.modifyProductDetail)
|
||||
self.modifyProductDetailSwitch_layout = self.create_label_and_switch("상세페이지 수정", self.modifyProductDetailSwitch)
|
||||
|
||||
|
||||
self.modifyImageTranslationSwitch = ToggleSwitch(self)
|
||||
self.modifyImageTranslationSwitch.move(10, 90)
|
||||
self.modifyImageTranslationSwitch.setChecked(False) # 기본 상태는 OFF
|
||||
self.modifyImageTranslationSwitch.clicked.connect(self.modifyImageTranslation)
|
||||
self.modifyImageTranslationSwitch_layout = self.create_label_and_switch("이미지 번역", self.modifyImageTranslationSwitch)
|
||||
|
||||
|
||||
self.uploadToMarketSwitch = ToggleSwitch(self)
|
||||
self.uploadToMarketSwitch.move(10, 90)
|
||||
self.uploadToMarketSwitch.setChecked(False) # 기본 상태는 OFF
|
||||
self.uploadToMarketSwitch.clicked.connect(self.uploadToMarket)
|
||||
self.uploadToMarketSwitch_layout = self.create_label_and_switch("마켓 업로드", self.uploadToMarketSwitch)
|
||||
|
||||
self.infoLabel4 = QtWidgets.QLabel(" 퍼센티 자동화 by 리앤수Int.")
|
||||
|
||||
|
||||
layout.addWidget(self.signupButton)
|
||||
layout.addWidget(self.infoLabel)
|
||||
layout.addWidget(self.emailInput)
|
||||
layout.addWidget(self.passwordInput)
|
||||
layout.addWidget(self.infoLabel2)
|
||||
layout.addWidget(self.per_emailInput)
|
||||
layout.addWidget(self.per_em_emailInput)
|
||||
layout.addWidget(self.per_em_passwordInput)
|
||||
layout.addWidget(self.per_passwordInput)
|
||||
layout.addWidget(self.changeModeButton)
|
||||
layout.addWidget(self.set_num_modifyInput)
|
||||
layout.addWidget(self.infoLabel5)
|
||||
layout.addWidget(self.infoLabel3)
|
||||
layout.addWidget(self.showPasswordCheckBox)
|
||||
layout.addWidget(self.loginButton)
|
||||
layout.addWidget(self.infoLabel4)
|
||||
login_layout.addWidget(self.infoLabel)
|
||||
|
||||
login_layout.addWidget(self.signupButton)
|
||||
login_layout.addWidget(self.infoLabel)
|
||||
login_layout.addWidget(self.emailInput)
|
||||
login_layout.addWidget(self.passwordInput)
|
||||
login_layout.addWidget(self.infoLabel2)
|
||||
login_layout.addWidget(self.per_emailInput)
|
||||
login_layout.addWidget(self.per_em_emailInput)
|
||||
login_layout.addWidget(self.per_em_passwordInput)
|
||||
login_layout.addWidget(self.per_passwordInput)
|
||||
login_layout.addWidget(self.changeModeButton)
|
||||
login_layout.addWidget(self.set_num_modifyInput)
|
||||
login_layout.addWidget(self.infoLabel5)
|
||||
login_layout.addWidget(self.infoLabel3)
|
||||
login_layout.addWidget(self.showPasswordCheckBox)
|
||||
login_layout.addWidget(self.loginButton)
|
||||
login_layout.addWidget(self.infoLabel4)
|
||||
|
||||
# labels = ["항상 위", "작업완료 후 PC종료", "상품명 수정", "옵션 수정", "가격 수정", "태그 수정", "썸네일 수정", "상세페이지 수정", "이미지 번역", "마켓 업로드"]
|
||||
# for i, label_text in enumerate(labels, start = 1):
|
||||
# label = QtWidgets.QLabel(label_text)
|
||||
# setting_layout.addWidget(label) # 설명 라벨은 2열(인덱스 1)에 배치
|
||||
|
||||
setting_layout.addLayout(self.modifyProductNameSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyProductOptionsSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyProductPriceSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyProductTagSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyProductThumbSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyProductDetailSwitch_layout)
|
||||
setting_layout.addLayout(self.modifyImageTranslationSwitch_layout)
|
||||
setting_layout.addLayout(self.uploadToMarketSwitch_layout)
|
||||
setting_layout.addLayout(self.alwaysOnTopSwitch_layout)
|
||||
setting_layout.addLayout(self.shutdownSwitch_layout)
|
||||
|
||||
self.setLayout(layout)
|
||||
self.setWindowTitle('AutoPercenty')
|
||||
|
||||
def create_label_and_switch(self, label_text, target_switch):
|
||||
layout = QtWidgets.QHBoxLayout()
|
||||
label = QtWidgets.QLabel(label_text)
|
||||
|
||||
layout.addWidget(label)
|
||||
layout.addWidget(target_switch)
|
||||
|
||||
return layout
|
||||
|
||||
def center(self):
|
||||
# 화면 중앙에 위치시키기 위한 계산
|
||||
qr = self.frameGeometry() # 위젯의 직사각형 정보를 얻습니다.
|
||||
cp = QtWidgets.QDesktopWidget().availableGeometry().center() # 사용 가능한 화면의 중앙 위치를 얻습니다.
|
||||
qr.moveCenter(cp) # 직사각형의 중심을 화면의 중심 위치로 이동시킵니다.
|
||||
self.move(qr.topLeft()) # 위젯의 시작점을 직사각형의 시작점으로 이동시켜 화면 중앙에 위치시킵니다.
|
||||
|
||||
|
||||
def toggleAlwaysOnTop(self, checked):
|
||||
if checked:
|
||||
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
|
||||
else:
|
||||
self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def shutdownAfterComplete(self, checked):
|
||||
if checked:
|
||||
self.whether_shutdownAfterComplete = True
|
||||
else:
|
||||
self.whether_shutdownAfterComplete = False
|
||||
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductName(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductName = True
|
||||
else:
|
||||
self.whether_modifyProductName = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductOptions(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductOptions = True
|
||||
else:
|
||||
self.whether_modifyProductOptions = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductTag(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductTag = True
|
||||
else:
|
||||
self.whether_modifyProductTag = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductPrice(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductPrice = True
|
||||
else:
|
||||
self.whether_modifyProductPrice = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductThumb(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductThumb = True
|
||||
else:
|
||||
self.whether_modifyProductThumb = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyProductDetail(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyProductDetail = True
|
||||
else:
|
||||
self.whether_modifyProductDetail = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
def modifyImageTranslation(self, checked):
|
||||
if checked:
|
||||
self.whether_modifyImageTanslation = True
|
||||
else:
|
||||
self.whether_modifyImageTanslation = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
|
||||
def uploadToMarket(self, checked):
|
||||
if checked:
|
||||
self.whether_uploadToMarket = True
|
||||
else:
|
||||
self.whether_uploadToMarket = False
|
||||
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
|
||||
|
||||
|
||||
def togglePasswordVisibility(self):
|
||||
if self.showPasswordCheckBox.isChecked():
|
||||
|
|
|
|||
44
main.py
44
main.py
|
|
@ -5,8 +5,10 @@ from selenium.webdriver.chrome.options import Options
|
|||
from selenium.webdriver.chrome.service import Service #웨일
|
||||
# from webdriver_manager.chrome import ChromeDriverManager #웨일
|
||||
import time
|
||||
import datetime
|
||||
import ctypes
|
||||
import atexit
|
||||
import platform, os, sys
|
||||
|
||||
from login import login
|
||||
import sys
|
||||
|
|
@ -56,6 +58,27 @@ def send_exit_message():
|
|||
# 이 함수에서는 사용자에게 프로그램 종료 메시지를 보내는 로직을 구현해야 합니다.
|
||||
# 여기서는 예시로 로깅만 수행합니다.
|
||||
logger.info("프로그램이 종료되었습니다. 안녕히 가세요.")
|
||||
|
||||
def shutdown_system():
|
||||
"""
|
||||
시스템을 종료시키는 메서드. 운영 체제를 확인하고 적절한 종료 명령을 실행합니다.
|
||||
"""
|
||||
logger.info("프로그램이 종료되었습니다. 1초 후 컴퓨터가 종료됩니다. 안녕히 가세요.")
|
||||
try:
|
||||
operating_system = platform.system()
|
||||
|
||||
if operating_system == "Windows":
|
||||
os.system("shutdown /s /t 1") # Windows에서 시스템 종료
|
||||
elif operating_system == "Linux" or operating_system == "Darwin":
|
||||
os.system("shutdown -h now") # Linux와 macOS에서 시스템 종료
|
||||
else:
|
||||
print("Unsupported operating system.")
|
||||
sys.exit(1)
|
||||
|
||||
print("System shutdown command executed.")
|
||||
except Exception as e:
|
||||
print(f"Failed to shutdown the system: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def DB_setting():
|
||||
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
|
||||
|
|
@ -79,22 +102,35 @@ def DB_setting():
|
|||
"per_em_password": login_widget.per_em_password,
|
||||
"per_mode": login_widget.per_mode,
|
||||
"set_num_modify": login_widget.set_num_modify,
|
||||
"login_result": login_widget.result # 로그인 결과도 함께 반환
|
||||
"alwaysOnTopSwitch": login_widget.alwaysOnTopSwitch,
|
||||
"whether_shutdownAfterComplete" : login_widget.whether_shutdownAfterComplete,
|
||||
"whether_modifyProductName": login_widget.whether_modifyProductName,
|
||||
"whether_modifyProductOptions": login_widget.whether_modifyProductOptions,
|
||||
"whether_modifyProductTag": login_widget.whether_modifyProductTag,
|
||||
"whether_modifyProductPrice": login_widget.whether_modifyProductPrice,
|
||||
"whether_modifyProductThumb": login_widget.whether_modifyProductThumb,
|
||||
"whether_modifyProductDetail": login_widget.whether_modifyProductDetail,
|
||||
"whether_modifyImageTanslation": login_widget.whether_modifyImageTanslation,
|
||||
"whether_uploadToMarket": login_widget.whether_uploadToMarket,
|
||||
"login_result": login_widget.result,
|
||||
}
|
||||
|
||||
return login_info, result, mongo_config
|
||||
|
||||
def main():
|
||||
|
||||
login_info, app_result, mongo_config = DB_setting() # 로그인 정보와 QApplication 실행 결과를 받음
|
||||
|
||||
# 화면 꺼짐과 절전 모드 방지 기능 활성화
|
||||
prevent_sleep_mode()
|
||||
|
||||
# 프로그램 종료 시 호출될 함수 등록
|
||||
atexit.register(restore_sleep_mode)
|
||||
atexit.register(record_logout_time)
|
||||
atexit.register(send_exit_message)
|
||||
|
||||
login_info, app_result, mongo_config = DB_setting() # 로그인 정보와 QApplication 실행 결과를 받음
|
||||
if login_info.whether_shutdownAfterComplete:
|
||||
atexit.register(shutdown_system)
|
||||
|
||||
atexit.register(send_exit_message)
|
||||
|
||||
if not login_info["login_result"]:
|
||||
logger.debug("사용자 인증 실패로 프로그램을 종료합니다.")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QPushButton, QTextEdit
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.chrome.service import Service #웨일
|
||||
# from webdriver_manager.chrome import ChromeDriverManager #웨일
|
||||
import time
|
||||
import ctypes
|
||||
import atexit
|
||||
|
||||
from login import login
|
||||
import sys
|
||||
from navigate import navigate_to_new_product_registration
|
||||
from modify_products import modify_products
|
||||
from database import setup_database
|
||||
from utils import log
|
||||
from config import WEBSITE_URL
|
||||
from credentials import load_credentials, save_credentials
|
||||
from ai.gemini import ImageDescriptionGenerator
|
||||
from login_widget import LoginWidget
|
||||
from mongo_config import MongoConfig
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from logger_module import setup_logger
|
||||
import logging
|
||||
class MainWindow(QWidget):
|
||||
def __init__(self, mongo_config, logger, CURRENT_VERSION):
|
||||
super().__init__()
|
||||
self.mongo_config = mongo_config
|
||||
self.logger = logger
|
||||
self.CURRENT_VERSION = CURRENT_VERSION
|
||||
self.initUI()
|
||||
|
||||
def initUI(self):
|
||||
self.setWindowTitle('AutoPercenty by 리앤수인터')
|
||||
self.setGeometry(300, 300, 600, 500) # 위치와 크기 설정
|
||||
|
||||
grid = QGridLayout()
|
||||
self.setLayout(grid)
|
||||
|
||||
# 로그인 정보와 작업 상태 정보 라벨 추가
|
||||
self.loginInfoLabel = QLabel('로그인 정보가 여기 표시됩니다.')
|
||||
grid.addWidget(self.loginInfoLabel, 0, 0, 1, 2)
|
||||
|
||||
self.workStatusLabel = QLabel('작업 상태 정보가 여기 표시됩니다.')
|
||||
grid.addWidget(self.workStatusLabel, 0, 2, 1, 1)
|
||||
|
||||
# 로그인 버튼 추가
|
||||
self.loginButton = QPushButton('로그인')
|
||||
self.loginButton.clicked.connect(self.openLoginWidget)
|
||||
grid.addWidget(self.loginButton, 1, 0)
|
||||
|
||||
# 로그 박스 추가
|
||||
self.logBox = QTextEdit()
|
||||
self.logBox.setReadOnly(True)
|
||||
grid.addWidget(self.logBox, 2, 0, 3, 3) # 2행 0열부터 4행 2열까지
|
||||
|
||||
def openLoginWidget(self):
|
||||
# 여기서 LoginWidget 인스턴스를 생성하고 표시합니다.
|
||||
self.login_widget = LoginWidget(self.mongo_config, self.CURRENT_VERSION)
|
||||
self.login_widget.show()
|
||||
|
||||
def main():
|
||||
CURRENT_VERSION = "1.0.1"
|
||||
app = QApplication(sys.argv)
|
||||
mongo_config = MongoConfig()
|
||||
logger = setup_logger('default_logger', 'application.log', level=logging.DEBUG)
|
||||
main_window = MainWindow(mongo_config, logger,CURRENT_VERSION)
|
||||
main_window.show()
|
||||
sys.exit(app.exec_())
|
||||
|
|
@ -14,6 +14,8 @@ from edit.options import modify_option_page
|
|||
from edit.price import modify_price_page
|
||||
from edit.title import modify_product_title
|
||||
from edit.thumbnail import modify_thumb_page
|
||||
from edit.trans_image import *
|
||||
from edit.uploadMarket import *
|
||||
from edit.action_elements import click_element, return_element, wait_element
|
||||
import logging
|
||||
|
||||
|
|
@ -63,6 +65,20 @@ logger = logging.getLogger('default_logger')
|
|||
# 'title_modification': modify_product_title,
|
||||
# }
|
||||
|
||||
def should_execute_step(step_name, login_info):
|
||||
if step_name == 'tag_modification':
|
||||
return login_info.whether_modifyProductTag
|
||||
elif step_name == 'thumbnail_modification':
|
||||
return login_info.whether_modifyProductThumb
|
||||
elif step_name == 'option_modification':
|
||||
return login_info.whether_modifyProductOptions
|
||||
elif step_name == 'detail_page_modification':
|
||||
return login_info.whether_modifyProductDetail
|
||||
elif step_name == 'price_modification':
|
||||
return login_info.whether_modifyProductPrice
|
||||
else:
|
||||
return True
|
||||
|
||||
def perform_step(db, step_name, action, current_user, *args):
|
||||
"""
|
||||
단계별 작업을 수행하는 함수.
|
||||
|
|
@ -170,11 +186,25 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
|
|||
('tag_modification', edit_tag, (driver, product_infos[i-1])),
|
||||
('thumbnail_modification', modify_thumb_page, (driver, product_infos[i-1])),
|
||||
('option_modification', modify_option_page, (driver, product_infos[i-1])),
|
||||
('detail_page_modification', modify_detail_page, (driver, product_infos[i-1], gemini, delv_collection, json_naver_codes)),
|
||||
# ('price_modification', modify_price_page, (driver, product_infos[i-1])),
|
||||
# 'title_modification' 단계와 관련된 함수 호출은 여기에 추가합니다.
|
||||
('detail_page_modification', modify_detail_page, (driver, product_infos[i-1], gemini, delv_collection, json_naver_codes, login_info)),
|
||||
('price_modification', modify_price_page, (driver, product_infos[i-1])),
|
||||
('title_modification', modify_product_title, (driver, product_infos[i-1])),
|
||||
('trans_detailImage', tran_detail_image, (driver, product_infos[i-1])),
|
||||
('upload_to_market', upload_to_market, (driver, product_infos[i-1])),
|
||||
]
|
||||
|
||||
# 상품 수정 관련 작업을 조건에 따라 수행하는 로직
|
||||
step_conditions = {
|
||||
'tag_modification': login_info.whether_modifyProductTag,
|
||||
'thumbnail_modification': login_info.whether_modifyProductThumb,
|
||||
'option_modification': login_info.whether_modifyProductOptions,
|
||||
'detail_page_modification': login_info.whether_modifyProductDetail,
|
||||
'price_modification': login_info.whether_modifyProductPrice,
|
||||
'title_modification': login_info.whether_modifyProductName,
|
||||
'trans_detailImage': login_info.whether_modifyImageTanslation,
|
||||
'upload_to_market': login_info.whether_uploadToMarket,
|
||||
}
|
||||
|
||||
# 상품ID 복사
|
||||
try:
|
||||
product_id_element = return_element(driver,"XPATH",f"//div[{i}]/li/div/div/div[2]/div/div/div/div[3]/div[3]/span[2]/span",10)
|
||||
|
|
@ -205,9 +235,11 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
|
|||
time.sleep(2)
|
||||
for step_name, action, args in steps_and_actions:
|
||||
if step_name in incomplete_steps:
|
||||
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
|
||||
autoPercentyProductsDB.finalize_product_processing(product_id, current_user, product_infos[i-1])
|
||||
logger.info(f"상품 ID {product_id}의 미완성 목록을 완성했습니다.")
|
||||
# 각 단계별 실행 여부 판단
|
||||
if step_conditions.get(step_name, False):
|
||||
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
|
||||
autoPercentyProductsDB.finalize_product_processing(product_id, current_user, product_infos[i-1])
|
||||
logger.info(f"상품 ID {product_id}의 미완성 목록을 완성했습니다.")
|
||||
pass
|
||||
else:
|
||||
# 여기에는 incomplete_steps가 False이거나 리스트의 길이가 6인 경우.
|
||||
|
|
@ -356,7 +388,9 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
|
|||
# 각 단계별로 수정 작업 수행
|
||||
|
||||
for step_name, action, args in steps_and_actions:
|
||||
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
|
||||
# 각 단계별 실행 여부 판단
|
||||
if step_conditions.get(step_name, False):
|
||||
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
|
||||
|
||||
# 모든 단계가 완료되었다면, 상품 처리 최종화
|
||||
autoPercentyProductsDB.finalize_product_processing(product_infos[i-1].id, current_user, product_infos[i-1])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, pyqtProperty, pyqtSignal, QPoint
|
||||
from PyQt5.QtGui import QPainter, QColor
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
class ToggleSwitch(QWidget):
|
||||
clicked = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(ToggleSwitch, self).__init__(parent)
|
||||
self.setFixedSize(60, 30)
|
||||
self._checked = False
|
||||
self._circle_color_checked = QColor('red')
|
||||
self._circle_color_unchecked = QColor('gray')
|
||||
self._background_color = QColor('white')
|
||||
self._circle_pos = QPoint(0, 0) # Circle's initial position.
|
||||
self.animation = QPropertyAnimation(self, b"circle_pos")
|
||||
self.animation.setDuration(250)
|
||||
|
||||
self._init_position()
|
||||
|
||||
@pyqtProperty(QPoint)
|
||||
def circle_pos(self):
|
||||
return self._circle_pos
|
||||
|
||||
@circle_pos.setter
|
||||
def circle_pos(self, pos):
|
||||
self._circle_pos = pos
|
||||
self.update()
|
||||
|
||||
def _init_position(self):
|
||||
if self._checked:
|
||||
self._circle_pos.setX(30)
|
||||
else:
|
||||
self._circle_pos.setX(0)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
self._checked = not self._checked
|
||||
self.clicked.emit(self._checked)
|
||||
self._update_animation()
|
||||
self.update()
|
||||
super(ToggleSwitch, self).mousePressEvent(event)
|
||||
|
||||
def _update_animation(self):
|
||||
if self._checked:
|
||||
self.animation.setStartValue(QPoint(0, 0))
|
||||
self.animation.setEndValue(QPoint(30, 0))
|
||||
else:
|
||||
self.animation.setStartValue(QPoint(30, 0))
|
||||
self.animation.setEndValue(QPoint(0, 0))
|
||||
self.animation.start()
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
painter.setPen(Qt.NoPen)
|
||||
painter.setBrush(self._background_color)
|
||||
painter.drawRoundedRect(QRect(0, 0, 60, 30), 15, 15)
|
||||
|
||||
circle_color = self._circle_color_checked if self._checked else self._circle_color_unchecked
|
||||
|
||||
painter.setBrush(circle_color)
|
||||
painter.drawEllipse(self._circle_pos.x(), self._circle_pos.y(), 30, 30)
|
||||
|
||||
def setChecked(self, checked):
|
||||
if self._checked != checked:
|
||||
self._checked = checked
|
||||
self._update_animation()
|
||||
self.update()
|
||||
Loading…
Reference in New Issue