1차 OUTPUT
This commit is contained in:
parent
5fb7ff0cb4
commit
e4e8f3a873
|
|
@ -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,
|
||||||
|
)
|
||||||
|
|
@ -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}")
|
||||||
|
|
@ -3,7 +3,7 @@ from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver.common.action_chains import ActionChains
|
from selenium.webdriver.common.action_chains import ActionChains
|
||||||
from selenium.webdriver.common.keys import Keys
|
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
|
# from utils import log
|
||||||
import time
|
import time
|
||||||
import sys, re
|
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:
|
while retry_count < max_retries:
|
||||||
try:
|
try:
|
||||||
return gemini.generate_description(image_src, product_title)
|
return gemini.generate_description(image_src, product_title)
|
||||||
except InternalServerError as e:
|
# except InternalServerError as e:
|
||||||
logger.debug(f"Retry {retry_count + 1}/{max_retries} for InternalServerError")
|
# 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)
|
time.sleep(wait_time)
|
||||||
wait_time *= 2 # Exponential backoff
|
wait_time *= 2 # Exponential backoff
|
||||||
retry_count += 1
|
retry_count += 1
|
||||||
|
|
@ -385,10 +390,10 @@ def modify_detail_page(driver, gemini, product_info, delv_collection, json_naver
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# cat = click_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10, 'js')
|
# 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)
|
# cat = return_element(driver, 'XPATH', '//div[8]/div/div/div[2]/div/div/div/span[2]/div/div', 10)
|
||||||
logger.debug(f"퍼센티 등록 화면에 표시된 카테고리 텍스트 : {cat.text}")
|
# logger.debug(f"퍼센티 등록 화면에 표시된 카테고리 텍스트 : {cat.text}")
|
||||||
product_info.per_cat_code = cat.text
|
# product_info.per_cat_code = cat.text
|
||||||
naver_code = find_naver_code(cat.text, json_naver_codes)
|
naver_code = find_naver_code(product_info.per_cat_code, json_naver_codes)
|
||||||
logger.debug(f"검색된 스스 캣코드 : {naver_code}")
|
logger.debug(f"검색된 스스 캣코드 : {naver_code}")
|
||||||
product_info.naver_code = naver_code
|
product_info.naver_code = naver_code
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -469,8 +474,10 @@ def modify_detail_page(driver, gemini, product_info, delv_collection, json_naver
|
||||||
logger.debug("네이버쇼핑 파싱 완료")
|
logger.debug("네이버쇼핑 파싱 완료")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
html_btn_xpath = "ck.ck-button.ck-source-editing-button.ck-off.ck-button_with-text"
|
html_btn_by_contains_xpath="//button[contains(.,'소스')]"
|
||||||
click_element(driver, 'XPATH', html_btn_xpath, 10, 'js')
|
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(
|
# html_btn = WebDriverWait(driver, 10).until(
|
||||||
# # EC.presence_of_element_located((By.CSS_SELECTOR, ".ck-source-editing-button"))
|
# # EC.presence_of_element_located((By.CSS_SELECTOR, ".ck-source-editing-button"))
|
||||||
# EC.presence_of_element_located(By.CLASS_NAME, html_btn_xpath)
|
# 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:
|
try:
|
||||||
textarea = WebDriverWait(driver, 10).until(
|
textarea = WebDriverWait(driver, 5).until(
|
||||||
EC.presence_of_element_located((By.CLASS_NAME, "ck-source-editing-area"))
|
EC.presence_of_element_located((By.CLASS_NAME, "ck-source-editing-area"))
|
||||||
)
|
)
|
||||||
logger.debug("textarea버튼을 성공적으로 찾았습니다.")
|
logger.debug("textarea버튼을 성공적으로 찾았습니다.")
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ def option_name_trans(driver, option_type_number, option_count, allowed_special_
|
||||||
# 원본 옵션명을 하나의 텍스트로 합치기
|
# 원본 옵션명을 하나의 텍스트로 합치기
|
||||||
combined_ori_optionNames = '\n\n'.join(ori_optionNames)
|
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)
|
cleaned_ori_text = replace_or_remove_special_chars(combined_ori_optionNames, allowed_special_chars, special_char_replacements)
|
||||||
|
|
||||||
logger.debug(f"원본옵션명 집합 \n {cleaned_ori_text}")
|
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 번역 함수
|
trans_optionNames_text = trans(cleaned_ori_text) # DeepL 번역 함수
|
||||||
|
|
||||||
logger.debug(f"번역된 텍스트 \n {trans_optionNames_text} ")
|
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')
|
trans_optionNames = trans_optionNames_text.split('\n\n')
|
||||||
logger.debug("번역 텍스트 나누기")
|
logger.debug("번역 텍스트 나누기")
|
||||||
|
|
|
||||||
|
|
@ -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"
|
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')
|
click_element(driver, 'XPATH', search_button_xpath, 10, 'js')
|
||||||
time.sleep(0.5)
|
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-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")
|
# add_all_keywords_button = driver.find_element(By.CSS_SELECTOR, ".sc-bizigk > .ant-row:nth-child(1) .ant-btn > span")
|
||||||
|
|
|
||||||
|
|
@ -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:
|
try:
|
||||||
product_title_element = WebDriverWait(driver, 10).until(
|
product_title_element = WebDriverWait(driver, 10).until(
|
||||||
EC.presence_of_element_located((By.XPATH, "//div[5]/div/span/input"))
|
EC.presence_of_element_located((By.XPATH, "//div[5]/div/span/input"))
|
||||||
|
|
|
||||||
4
main.py
4
main.py
|
|
@ -55,11 +55,11 @@ def main():
|
||||||
per_email = login_info["per_email"]
|
per_email = login_info["per_email"]
|
||||||
logger.debug(f'per_email : {per_email}')
|
logger.debug(f'per_email : {per_email}')
|
||||||
per_password = login_info["per_password"]
|
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"]
|
per_em_email = login_info["per_em_email"]
|
||||||
logger.debug(f'per_em_email : {per_em_email}')
|
logger.debug(f'per_em_email : {per_em_email}')
|
||||||
per_em_password = login_info["per_em_password"]
|
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"]
|
per_mode = login_info["per_mode"]
|
||||||
logger.debug(f'per_mode : {per_mode}')
|
logger.debug(f'per_mode : {per_mode}')
|
||||||
set_num_modify = login_info["set_num_modify"]
|
set_num_modify = login_info["set_num_modify"]
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ a = Analysis(
|
||||||
['main.py'],
|
['main.py'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
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'],
|
hiddenimports=['shapely', 'pyclipper', 'imghdr', 'skimage', 'skimage.morphology._skeletonize', 'imgaug', 'scipy.io', 'lmdb', 'tqdm', 'paddlepaddle.core'],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
|
|
|
||||||
|
|
@ -126,13 +126,13 @@ def modify_products(driver, gemini, mongo_config, set_num_modify):
|
||||||
product_id = product_id_element.get_attribute('innerText')
|
product_id = product_id_element.get_attribute('innerText')
|
||||||
product_id_set = f"ID:{product_id}"
|
product_id_set = f"ID:{product_id}"
|
||||||
product_infos[i-1].id = product_id_set
|
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:
|
except Exception as e:
|
||||||
logger.debug(f"상품ID 복사 중 오류 발생: 요소를 찾을 수 없습니다. : {e}")
|
logger.debug(f"상품ID 복사 중 오류 발생: 요소를 찾을 수 없습니다. : {e}")
|
||||||
|
|
||||||
# 상품ID 처리 여부 판단
|
# 상품ID 처리 여부 판단
|
||||||
if is_product_processed(product_id):
|
if is_product_processed(product_id_set):
|
||||||
logger.debug(f"상품 {product_id}는 이미 처리됨.")
|
logger.debug(f"상품 {product_id_set}는 이미 처리됨.")
|
||||||
# close_button = driver.find_element(By.CSS_SELECTOR, ".anticon-close path")
|
# close_button = driver.find_element(By.CSS_SELECTOR, ".anticon-close path")
|
||||||
# close_button.click()
|
# close_button.click()
|
||||||
continue
|
continue
|
||||||
|
|
@ -232,6 +232,12 @@ def modify_products(driver, gemini, mongo_config, set_num_modify):
|
||||||
logger.debug("상품 수정 페이지 클릭")
|
logger.debug("상품 수정 페이지 클릭")
|
||||||
time.sleep(2)
|
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")
|
# # image_element = driver.find_element(By.XPATH, "//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/img")
|
||||||
# try:
|
# try:
|
||||||
|
|
@ -282,7 +288,8 @@ def modify_products(driver, gemini, mongo_config, set_num_modify):
|
||||||
logger.debug("가격 수정작업 완료")
|
logger.debug("가격 수정작업 완료")
|
||||||
|
|
||||||
logger.debug("상품명 수정작업 시작")
|
logger.debug("상품명 수정작업 시작")
|
||||||
modify_product_title(driver, product_infos[i-1])
|
# modify_product_title(driver, product_infos[i-1])
|
||||||
|
logger.debug("......상품명 메서드 작성 중......")
|
||||||
logger.debug("상품명 수정작업 완료")
|
logger.debug("상품명 수정작업 완료")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Loading…
Reference in New Issue