diff --git a/AutoPercenty.spec b/AutoPercenty.spec new file mode 100644 index 0000000..34f7572 --- /dev/null +++ b/AutoPercenty.spec @@ -0,0 +1,36 @@ +# -*- mode: python ; coding: utf-8 -*- + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[('E:\\py\\AutoPercenty\\Lib\\site-packages\\paddleocr', 'paddleocr'), ('E:\\py\\AutoPercenty\\models', 'models'), ('E:\\py\\AutoPercenty\\Lib\\site-packages\\paddle\\libs\\*.dll', 'paddle\\libs'), ('E:\\py\\AutoPercenty\\config.ini', '.')], + hiddenimports=['shapely', 'pyclipper', 'imghdr', 'skimage', 'skimage.morphology._skeletonize', 'imgaug', 'scipy.io', 'lmdb', 'tqdm', 'paddlepaddle.core'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure, a.zipped_data) +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='AutoPercenty', + debug=True, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + onefile=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/leensoo1nt_service_key.json b/ai/leensoo1nt_service_key.json similarity index 100% rename from leensoo1nt_service_key.json rename to ai/leensoo1nt_service_key.json diff --git a/ai/ver.py b/ai/ver.py new file mode 100644 index 0000000..911046d --- /dev/null +++ b/ai/ver.py @@ -0,0 +1,58 @@ +import io +import json +import os +import urllib.request + +from collections import Counter + +from google.cloud import vertexai +# JSON 파일 경로 +json_file_path = "leensoo1nt_service_key.json" + +# Vertex AI Prediction 서비스 엔드포인트 +endpoint = "https://us-central1-aiplatform.googleapis.com/v1/projects/YOUR_PROJECT_ID/locations/us-central1/models/gemini-pro" + +# Vertex AI Prediction 서비스에 사용할 크레덴셜 +credentials, _ = vertexai.auth.google_auth() +def extract_product_info(product_name, image_url): + # 이미지 URL로부터 이미지 바이트 데이터 읽어오기 + image_bytes = io.BytesIO(urllib.request.urlopen(image_url).read()) + + # 요청 객체 생성 + request = { + "inputs": [ + { + "image_bytes": image_bytes.getvalue(), + }, + {"text": product_name}, + ] + } + + # Vertex AI Prediction 서비스에 요청 + response = vertexai.prediction.predict( + endpoint=endpoint, + instances=request, + credentials=credentials, + ) + + # 추출 결과 + product_description = response["predictions"][0]["text"] + product_weight = response["predictions"][0]["weight"] + + # 홍보 문구 생성 + # promotional_phrases = generate_promotional_phrases(product_description) + + return product_description, promotional_phrases, product_weight + + +# 상품명 및 이미지 URL 입력 +product_name = "음식물 쓰레기통" +image_url = "https://file.percenty.co.kr/public/652bed8e865b1f32ea62bf1f/products/66063feb4de44a71b14f2b6a/aac95c72-7155-41e9-b27d-f34b51f00a29.jpg" + +# 정보 추출 및 홍보 문구 생성 +product_description, promotional_phrases, product_weight = extract_product_info(product_name, image_url) + +# 결과 출력 +print(f"상품 설명: {product_description}") +print(f"홍보 문구: {promotional_phrases}") +print(f"상품 무게: {product_weight}") diff --git a/edit/detail1.py b/edit/detail1.py index 3a658ab..f288ea2 100644 --- a/edit/detail1.py +++ b/edit/detail1.py @@ -3,7 +3,7 @@ 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 -from google.api_core.exceptions import InternalServerError +# from google.api_core.exceptions import InternalServerError # from utils import log import time import sys, re @@ -79,8 +79,13 @@ def safe_generate_content(gemini, image_src, product_title, max_retries=3, initi while retry_count < max_retries: try: return gemini.generate_description(image_src, product_title) - except InternalServerError as e: - logger.debug(f"Retry {retry_count + 1}/{max_retries} for InternalServerError") + # except InternalServerError as e: + # logger.debug(f"Retry {retry_count + 1}/{max_retries} for InternalServerError") + # time.sleep(wait_time) + # wait_time *= 2 # Exponential backoff + # retry_count += 1 + except Exception as e: + logger.debug(f"예외 발생으로 재시도 : {retry_count + 1}/{max_retries}") time.sleep(wait_time) wait_time *= 2 # Exponential backoff retry_count += 1 @@ -385,10 +390,10 @@ def modify_detail_page(driver, gemini, product_info, delv_collection, json_naver try: # cat = click_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10, 'js') - cat = return_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10) - logger.debug(f"퍼센티 등록 화면에 표시된 카테고리 텍스트 : {cat.text}") - product_info.per_cat_code = cat.text - naver_code = find_naver_code(cat.text, json_naver_codes) + # cat = return_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10) + # logger.debug(f"퍼센티 등록 화면에 표시된 카테고리 텍스트 : {cat.text}") + # product_info.per_cat_code = cat.text + naver_code = find_naver_code(product_info.per_cat_code, json_naver_codes) logger.debug(f"검색된 스스 캣코드 : {naver_code}") product_info.naver_code = naver_code except Exception as e: @@ -469,8 +474,10 @@ def modify_detail_page(driver, gemini, product_info, delv_collection, json_naver logger.debug("네이버쇼핑 파싱 완료") try: - html_btn_xpath = "ck.ck-button.ck-source-editing-button.ck-off.ck-button_with-text" - click_element(driver, 'XPATH', html_btn_xpath, 10, 'js') + html_btn_by_contains_xpath="//button[contains(.,'소스')]" + html_btn_css = "ck.ck-button.ck-source-editing-button.ck-off.ck-button_with-text" + html_btn_xpath="//div[@id='productMainContentContainerId']/div/div/div[2]/div[2]/div/div/div[2]/div/div/button[8]" + click_element(driver, 'XPATH', html_btn_xpath, 5, 'js') # html_btn = WebDriverWait(driver, 10).until( # # EC.presence_of_element_located((By.CSS_SELECTOR, ".ck-source-editing-button")) # EC.presence_of_element_located(By.CLASS_NAME, html_btn_xpath) @@ -487,7 +494,7 @@ def modify_detail_page(driver, gemini, product_info, delv_collection, json_naver try: - textarea = WebDriverWait(driver, 10).until( + textarea = WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.CLASS_NAME, "ck-source-editing-area")) ) logger.debug("textarea버튼을 성공적으로 찾았습니다.") diff --git a/edit/options.py b/edit/options.py index 464b310..39b2bd7 100644 --- a/edit/options.py +++ b/edit/options.py @@ -252,7 +252,7 @@ def option_name_trans(driver, option_type_number, option_count, allowed_special_ # 원본 옵션명을 하나의 텍스트로 합치기 combined_ori_optionNames = '\n\n'.join(ori_optionNames) - logger.debug("특수문자 제거 및 대체") + logger.debug("원본 텍스트의 특수문자 제거 및 대체") cleaned_ori_text = replace_or_remove_special_chars(combined_ori_optionNames, allowed_special_chars, special_char_replacements) logger.debug(f"원본옵션명 집합 \n {cleaned_ori_text}") @@ -261,7 +261,9 @@ def option_name_trans(driver, option_type_number, option_count, allowed_special_ trans_optionNames_text = trans(cleaned_ori_text) # DeepL 번역 함수 logger.debug(f"번역된 텍스트 \n {trans_optionNames_text} ") - + + logger.debug("번역 텍스트의 특수문자 제거 및 대체") + cleaned_ori_text = replace_or_remove_special_chars(trans_optionNames_text, allowed_special_chars, special_char_replacements) trans_optionNames = trans_optionNames_text.split('\n\n') logger.debug("번역 텍스트 나누기") diff --git a/edit/tag.py b/edit/tag.py index 8db2fc2..d8c3626 100644 --- a/edit/tag.py +++ b/edit/tag.py @@ -70,7 +70,12 @@ def edit_tag(driver, product_infos): search_button_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div[2]/div/div/div[3]/div[2]/button" click_element(driver, 'XPATH', search_button_xpath, 10, 'js') time.sleep(0.5) - + + # 첫번째 키워드 검색결과가 나타난 후 모두 추가 버튼 클릭 + first_tag_xpath="//div[@id='productMainContentContainerId']/div/div/div/div[2]/div/div/div[4]/div/span" + click_element(driver, 'XPATH', first_tag_xpath, 10, 'js') + time.sleep(0.5) + # 모든 키워드 추가 버튼 클릭 # add_all_keywords_button = driver.find_element(By.CSS_SELECTOR, ".sc-hpGnlu > .ant-row:nth-child(1) .ant-btn > span") # add_all_keywords_button = driver.find_element(By.CSS_SELECTOR, ".sc-bizigk > .ant-row:nth-child(1) .ant-btn > span") diff --git a/edit/title.py b/edit/title.py index ed3bc02..1d14f2b 100644 --- a/edit/title.py +++ b/edit/title.py @@ -26,7 +26,10 @@ def modify_product_title(driver, product_infos): #상품명 복사 - product_title_element = driver.find_element(By.XPATH, "//div[@id='productMainContentContainerId']/div/div/div/div/div[5]/div/span/input") + # 원본상품명 + tao_title_text = "//div[@id='productMainContentContainerId']/div/div/div[6]/div/div/span" + original_title_xpath="//div[@id='productMainContentContainerId']/div/div/div[6]/div[2]/div/span" + # product_title_element = driver.find_element(By.XPATH, "//div[@id='productMainContentContainerId']/div/div/div/div/div[5]/div/span/input") try: product_title_element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//div[5]/div/span/input")) diff --git a/main.py b/main.py index 635c104..b84696b 100644 --- a/main.py +++ b/main.py @@ -55,11 +55,11 @@ def main(): per_email = login_info["per_email"] logger.debug(f'per_email : {per_email}') per_password = login_info["per_password"] - logger.debug(f'per_password : {per_password}') + # logger.debug(f'per_password : {per_password}') per_em_email = login_info["per_em_email"] logger.debug(f'per_em_email : {per_em_email}') per_em_password = login_info["per_em_password"] - logger.debug(f'per_em_password : {per_em_password}') + # logger.debug(f'per_em_password : {per_em_password}') per_mode = login_info["per_mode"] logger.debug(f'per_mode : {per_mode}') set_num_modify = login_info["set_num_modify"] diff --git a/main.spec b/main.spec index 48b9222..20dfc3b 100644 --- a/main.spec +++ b/main.spec @@ -4,7 +4,7 @@ a = Analysis( ['main.py'], pathex=[], binaries=[], - datas=[('H:\\py\\per368\\Lib\\site-packages\\paddleocr', 'paddleocr'), ('H:\\py\\per368\\models', 'models'), ('H:\\py\\per368\\Lib\\site-packages\\paddle\\libs\\*.dll', 'paddle\\libs'), ('H:\\py\\per368\\config.ini', '.')], + datas=[('E:\\py\\AutoPercenty\\Lib\\site-packages\\paddleocr', 'paddleocr'), ('E:\\py\\AutoPercenty\\models', 'models'), ('E:\\py\\AutoPercenty\\Lib\\site-packages\\paddle\\libs\\*.dll', 'paddle\\libs'), ('E:\\py\\AutoPercenty\\config.ini', '.')], hiddenimports=['shapely', 'pyclipper', 'imghdr', 'skimage', 'skimage.morphology._skeletonize', 'imgaug', 'scipy.io', 'lmdb', 'tqdm', 'paddlepaddle.core'], hookspath=[], hooksconfig={}, diff --git a/modify_products.py b/modify_products.py index 02d856b..b71579e 100644 --- a/modify_products.py +++ b/modify_products.py @@ -126,13 +126,13 @@ def modify_products(driver, gemini, mongo_config, set_num_modify): product_id = product_id_element.get_attribute('innerText') product_id_set = f"ID:{product_id}" product_infos[i-1].id = product_id_set - logger.debug(f"상품ID : {product_id}") + logger.debug(f"상품ID : {product_id_set}") except Exception as e: logger.debug(f"상품ID 복사 중 오류 발생: 요소를 찾을 수 없습니다. : {e}") # 상품ID 처리 여부 판단 - if is_product_processed(product_id): - logger.debug(f"상품 {product_id}는 이미 처리됨.") + if is_product_processed(product_id_set): + logger.debug(f"상품 {product_id_set}는 이미 처리됨.") # close_button = driver.find_element(By.CSS_SELECTOR, ".anticon-close path") # close_button.click() continue @@ -232,6 +232,12 @@ def modify_products(driver, gemini, mongo_config, set_num_modify): logger.debug("상품 수정 페이지 클릭") time.sleep(2) + # 상품수정 페이지에 표시된 퍼센티카테고리 텍스트 수집 + per_cat = return_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10) + logger.debug(f"퍼센티 등록 화면에 표시된 카테고리 텍스트 : {per_cat.text}") + product_infos[i-1].per_cat_code = per_cat.text + + # # 이미지 주소 복사 # # image_element = driver.find_element(By.XPATH, "//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/img") # try: @@ -282,7 +288,8 @@ def modify_products(driver, gemini, mongo_config, set_num_modify): logger.debug("가격 수정작업 완료") logger.debug("상품명 수정작업 시작") - modify_product_title(driver, product_infos[i-1]) + # modify_product_title(driver, product_infos[i-1]) + logger.debug("......상품명 메서드 작성 중......") logger.debug("상품명 수정작업 완료") diff --git a/requirements.txt b/requirements.txt index 1c7a1f2..87d9907 100644 Binary files a/requirements.txt and b/requirements.txt differ