From 8f96b7198d5e228b4e0747e429063e8fc182a7c8 Mon Sep 17 00:00:00 2001 From: R5600U_PC Date: Tue, 9 Apr 2024 16:12:09 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=94=EA=B0=80=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ai/deepl_with_playwright.py | 106 +++- edit/detail1.py | 51 +- ...{detail1_a.py => detail_with_img_trans.py} | 509 +++++++++--------- edit/ns.py | 188 +++++++ edit/options.py | 34 +- edit/price.py | 224 ++++---- edit/price_cal.py | 16 +- img_trans/image_trans.py | 4 +- img_trans/src/translation.py | 23 +- login_widget.py | 12 +- main.py | 11 +- modify_products.py | 27 +- naver_search.py | 8 +- 13 files changed, 756 insertions(+), 457 deletions(-) rename edit/{detail1_a.py => detail_with_img_trans.py} (61%) create mode 100644 edit/ns.py diff --git a/ai/deepl_with_playwright.py b/ai/deepl_with_playwright.py index cfe8d89..c4e90ee 100644 --- a/ai/deepl_with_playwright.py +++ b/ai/deepl_with_playwright.py @@ -1,5 +1,4 @@ from playwright.sync_api import sync_playwright -<<<<<<< HEAD import random import logging @@ -11,23 +10,25 @@ def trans_text(original_text): try: # Playwright 브라우저 인스턴스 생성 (헤드리스 모드) browser = p.chromium.launch(headless=True) # 여기서 headless=False로 설정하면 GUI 모드로 실행 - page = browser.new_page() - - # PC 사용자 에이전트 중 하나를 랜덤하게 선택 - USER_AGENTS = [ - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.0.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 OPR/85.0.0.0" - ] - random_user_agent = random.choice(USER_AGENTS) - - context = browser.new_context(user_agent=random_user_agent) + + # 동영상 녹화 설정을 포함하여 브라우저 컨텍스트 생성 + context = browser.new_context( + user_agent=random.choice([ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.0.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 OPR/85.0.0.0" + ]), + # # 동영상 녹화 설정 추가 + # record_video_dir="videos/", # 동영상이 저장될 디렉토리 지정 + # record_video_size={"width": 1280, "height": 720} # 동영상 크기 지정 + ) page = context.new_page() # DeepL 웹사이트 접속 - page.goto('https://www.deepl.com/ko/translator') + # page.goto('https://www.deepl.com/ko/translator') + page.goto('https://www.deepl.com/translator#zh/ko/'+ original_text) # JavaScript를 사용하여 편집 가능한 div에 텍스트 입력 page.evaluate("""(text) => { @@ -42,7 +43,9 @@ def trans_text(original_text): # "visible": 요소가 DOM에 삽입되어 있으며 렌더링된 상태(화면에 보이는 상태)임을 의미합니다. CSS를 통해 숨겨진 요소는 visible 상태에 해당하지 않습니다. # "hidden": 요소가 DOM에 존재하지 않거나 렌더링되지 않아 화면에 보이지 않음을 의미합니다. 이는 요소가 아예 존재하지 않거나, CSS 등을 통해 숨겨진 경우에 해당합니다. # timeout=10000 (10초 내에 해당요소가 "state" 될때까지 대기) - page.wait_for_function('document.querySelector("[data-testid="translator-target-input"]").textContent.length > 0') + # page.wait_for_function('document.querySelector("[data-testid="translator-target-input"]").textContent.length > 0') + # page.wait_for_function('document.querySelector(\'[data-testid="translator-target-input"]\').textContent.length > 0') + page.wait_for_function("document.querySelector(\"[data-testid='translator-target-input']\").textContent.length > 0") page.wait_for_selector('[data-testid="translator-target-input"]', state="visible", timeout=10000) translated_text = page.text_content('[data-testid="translator-target-input"]') @@ -68,10 +71,75 @@ def trans_text(original_text): return "에러발생으로 인한 번역 실패." finally: - if browser: # browser가 초기화되었는지 확인 + if context: # context가 초기화되었는지 확인하고, 종료 + context.close() + if browser: # browser가 초기화되었는지 확인하고, 종료 browser.close() logger.info("playwright Browser 닫힘.") return translated_text -======= ->>>>>>> 4b4ff58484a1cc6a2080061367ea02ec8d38e8b7 + +def trans_list_text(original_texts): + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) # 여기서 headless=False로 설정하면 GUI 모드로 실행 + # 동영상 녹화 설정을 포함하여 브라우저 컨텍스트 생성 + context = browser.new_context( + user_agent=random.choice([ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.0.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 OPR/85.0.0.0" + ]), + # # 동영상 녹화 설정 추가 + # record_video_dir="videos/", # 동영상이 저장될 디렉토리 지정 + # record_video_size={"width": 1280, "height": 720} # 동영상 크기 지정 + ) + page = context.new_page() + page.goto('https://www.deepl.com/translator#zh/ko/') + + translated_texts = [] # 번역된 텍스트를 저장할 리스트 + + for text in original_texts: + # contenteditable 속성을 가진 div에 텍스트를 직접 설정 + # page.evaluate("""(text) => { + # const editor = document.querySelector('[data-testid="translator-source-input"] div[contenteditable="true"]'); + # editor.textContent = text; + # }""", text) + + page.evaluate("""(text) => { + const editor = document.querySelector('[data-testid="translator-source-input"] div[contenteditable="true"]'); + editor.textContent = text; + const inputEvent = new Event('input', { bubbles: true }); + editor.dispatchEvent(inputEvent); + }""", text) + # 번역이 완료될 때까지 기다림 + + page.wait_for_function("document.querySelector(\"[data-testid='translator-target-input']\").textContent.length > 0") + + page.wait_for_selector('[data-testid="translator-target-input"]', state="visible", timeout=10000) + + # 번역된 텍스트 추출 + translated_text = page.text_content('[data-testid="translator-target-input"]') + translated_texts.append(translated_text.strip()) + + browser.close() + return translated_texts + +# ttt = ''' +# 贴片款(小号) 240*300mm\n\n +# 贴片款(中号) 440*315mm\n\n +# 贴片款(大号) 590*440mm\n\n +# ''' +# tttt = trans_text(ttt) + + +# # test = [] +# # test.append('贴片款(小号) 240*300mm') +# # test.append('贴片款(中号) 440*315mm') +# # test.append('贴片款(大号) 590*440mm') + +# # translated_text = trans_list_text(test) + + +# print(f"번역된 글자 : {ttt}") \ No newline at end of file diff --git a/edit/detail1.py b/edit/detail1.py index 39ec0be..bd4c20b 100644 --- a/edit/detail1.py +++ b/edit/detail1.py @@ -240,6 +240,17 @@ def find_delivery_fee(weight, delv_collection): # return product_info_text +def original_html(current_html): + # BeautifulSoup 객체 생성 + soup = BeautifulSoup(current_html, 'html.parser') + + # "img class='image_resized'" 태그만 추출 + resized_images = soup.find_all('img', class_='image_resized') + + # 추출된 태그들로 새로운 HTML 문자열 생성 + original_html_text = ''.join(str(tag) for tag in resized_images) + + return original_html_text def NS_info_with_HTML(products): # 상품 정보를 담을 5x1 표 생성 @@ -534,16 +545,17 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver try: # # data-value 속성 값을 가져옵니다. current_value = textarea.get_attribute("data-value") + original_html_tags = original_html(current_value) # logger.debug(f"현재 속성값 :{current_value}") - product_info.current_value = current_value + product_info.current_value = original_html_tags logger.debug("현재 속성값 수집 완료") # # ============번역을 위한 사전작업============ # 이미지 Url 수집 # translated_image_urls = [] # 번역된 이미지 URL들을 저장할 리스트 - detail_images = fetch_image_urls(current_value) - logger.debug(f"detail_images URLs \n {detail_images}") + detail_images = fetch_image_urls(original_html_tags) + # logger.debug(f"detail_images URLs \n {detail_images}") product_info.detail_image_urls = detail_images # 원본 URL을 빈문자열로 대체 @@ -554,26 +566,24 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver # # ============번역을 위한 사전작업============ logger.debug("product_info_card 결합.") - new_value = product_info_card + cost_add_text + current_value + new_value = product_info_card +'

' + cost_add_text +'

' +original_html_tags # textarea.send_keys(product_info_card) time.sleep(0.2) logger.debug("결합.") # 결합된 값을 다시 textarea에 설정 - try: - # # data-value 속성을 새로운 값으로 설정합니다. - driver.execute_script("arguments[0].setAttribute('data-value', arguments[1]);", textarea, new_value) - - # # driver.execute_script("arguments[0].innerHTML = arguments[1]", textarea, new_value) - # # driver.execute_script("arguments[0].innerHTML = arguments[1]", detail_content, new_value); + # # data-value 속성을 새로운 값으로 설정합니다. + driver.execute_script("arguments[0].setAttribute('data-value', arguments[1]);", textarea, new_value) + + # # driver.execute_script("arguments[0].innerHTML = arguments[1]", textarea, new_value) + # # driver.execute_script("arguments[0].innerHTML = arguments[1]", detail_content, new_value); + + # # JavaScript를 사용하여 textarea 값 설정 + # script = "arguments[0].value = arguments[1];" + # driver.execute_script(script, textarea, new_value) + time.sleep(0.5) + logger.debug("새로운 값이 성공적으로 설정됨.") - # # JavaScript를 사용하여 textarea 값 설정 - # script = "arguments[0].value = arguments[1];" - # driver.execute_script(script, textarea, new_value) - time.sleep(0.5) - logger.debug("새로운 값이 성공적으로 설정됨.") - except Exception as e: - logger.error(f"새로운 값 설정 중 오류 발생: {e}", exc_info=True) time.sleep(0.2) # textarea.send_keys(Keys.ENTER) @@ -626,8 +636,10 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver + trans_img_tag = login_info["whether_modifyImageTanslation"] + logger.debug(f"whether_modifyImageTanslation : {trans_img_tag}") - if login_info.whether_modifyImageTanslation: + if login_info["whether_modifyImageTanslation"]: logger.debug("상세페이지 이미지 번역 시작") try: for i, detail_image in enumerate(detail_images): @@ -650,9 +662,6 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver logger.debug("====번역이미지 붙여넣기 완료=====") - - - logger.debug("상세페이지 편집 저장") click_element(driver, "XPATH", save_button_xpath, 5, 'js') diff --git a/edit/detail1_a.py b/edit/detail_with_img_trans.py similarity index 61% rename from edit/detail1_a.py rename to edit/detail_with_img_trans.py index ff1d9f0..7ad5433 100644 --- a/edit/detail1_a.py +++ b/edit/detail_with_img_trans.py @@ -10,7 +10,7 @@ import sys, re import numpy as np from naver_search import parse_naver_shopping from edit.naver_code import find_naver_code -from edit.action_elements import click_element, return_element +from edit.action_elements import click_element, return_element, click_and_confirm_tab from img_trans.image_trans import image_trans import logging from bs4 import BeautifulSoup @@ -22,6 +22,7 @@ logger = logging.getLogger('default_logger') avg_price = 0 + def paste_image_in_editor(driver, editor_element): action = ActionChains(driver) action.click(editor_element) # 에디터를 클릭하여 포커스를 맞춥니다. @@ -72,27 +73,25 @@ def fetch_image_urls(html_content): return image_urls -def safe_generate_content(gemini, image_src, product_title, max_retries=3, initial_wait=1): +def safe_generate_content(gemini, product_info, max_retries=3, initial_wait=1): retry_count = 0 wait_time = initial_wait while retry_count < max_retries: try: - return gemini.generate_description(image_src, product_title) + return gemini.generate_description(product_info) # 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"예외 발생 : {e}", exc_info=True) logger.debug(f"예외 발생으로 재시도 : {retry_count + 1}/{max_retries}") time.sleep(wait_time) wait_time *= 2 # Exponential backoff retry_count += 1 - # Final attempt without catching the exception - return gemini.generate_content(image_src, product_title) - def selling_price(tao_bao_price, shipping_fee=6500, target_margin_rate=0.29, market_fee_rate=0.13, card_fee_rate=0.035, exchange_rate=200): """ @@ -186,65 +185,76 @@ def find_delivery_fee(weight, delv_collection): return fees[closest_weight_index] #네이버쇼핑 함수 -def NS_info(products): - # 각 상품 정보에 접근하여 텍스트로 가공 - product_info_text = "" - global avg_price - avg_price = 0 - prices = [] +# def NS_info(products): +# # 각 상품 정보에 접근하여 텍스트로 가공 +# product_info_text = "" +# global avg_price +# avg_price = 0 +# prices = [] - for index, product in enumerate(products): - idx = index + 1 - product_info_text += '
\n' # 카드 시작 태그 - product_info_text += f"=================={idx} 번째 네이버 상품========================" - # 이미지 태그 - product_info_text += f'상품 이미지\n' +# for index, product in enumerate(products): +# idx = index + 1 +# product_info_text += '
\n' # 카드 시작 태그 +# product_info_text += f"=================={idx} 번째 네이버 상품========================" +# # 이미지 태그 +# product_info_text += f'상품 이미지\n' - # 상품 세부 정보 태그 시작 - product_info_text += '
\n' +# # 상품 세부 정보 태그 시작 +# product_info_text += '
\n' - # 상품명 태그 - # product_info_text += f'
상품명 : {product["productTitle"]}
\n' - product_info_text += f'

상품명 : {product["productTitle"]}

\n' - # 가격 태그 - # 상품 가격을 숫자로 변환하고 포맷 - if isinstance(product["price"], str): - # 문자열인 경우 숫자로 변환 - price = int(product["price"].replace(",", "")) # 쉼표 제거 후 정수 변환 - else: - price = product["price"] # 이미 숫자인 경우 변환 없음 +# # 상품명 태그 +# # product_info_text += f'
상품명 : {product["productTitle"]}
\n' +# product_info_text += f'

상품명 : {product["productTitle"]}

\n' +# # 가격 태그 +# # 상품 가격을 숫자로 변환하고 포맷 +# if isinstance(product["price"], str): +# # 문자열인 경우 숫자로 변환 +# price = int(product["price"].replace(",", "")) # 쉼표 제거 후 정수 변환 +# else: +# price = product["price"] # 이미 숫자인 경우 변환 없음 - prices.append(price) - formatted_price = format(price, ",") + "원" # 천 단위 구분으로 포맷 - product_info_text += f'
가격: {formatted_price}
' +# prices.append(price) +# formatted_price = format(price, ",") + "원" # 천 단위 구분으로 포맷 +# product_info_text += f'
가격: {formatted_price}
' - # 순위 태그 - product_info_text += f'
순위: {product["rank"]}
\n' +# # 순위 태그 +# product_info_text += f'
순위: {product["rank"]}
\n' - product_info_text += "==================================================================" +# product_info_text += "==================================================================" - # 상품 세부 정보 태그 종료 - product_info_text += '
\n' +# # 상품 세부 정보 태그 종료 +# product_info_text += '
\n' - product_info_text += '
\n' # 카드 종료 태그 - avg_price += int(product["price"]) +# product_info_text += '
\n' # 카드 종료 태그 +# avg_price += int(product["price"]) - # avg_price = round(avg_price/len(products),0) +# # avg_price = round(avg_price/len(products),0) - if products: # products가 비어 있지 않은 경우에만 평균 가격 계산 - avg_price = round(avg_price / len(products), 0) - low_price = min(prices) - high_price = max(prices) - product_info_text += f'네이버 상품의 최저 가격은 [{low_price}]' - product_info_text += f'네이버 상품의 평균 가격은 [{avg_price}]' - product_info_text += f'네이버 상품의 최고 가격은 [{high_price}]' +# if products: # products가 비어 있지 않은 경우에만 평균 가격 계산 +# avg_price = round(avg_price / len(products), 0) +# low_price = min(prices) +# high_price = max(prices) +# product_info_text += f'네이버 상품의 최저 가격은 [{low_price}]' +# product_info_text += f'네이버 상품의 평균 가격은 [{avg_price}]' +# product_info_text += f'네이버 상품의 최고 가격은 [{high_price}]' - return product_info_text +# return product_info_text +def original_html(current_html): + # BeautifulSoup 객체 생성 + soup = BeautifulSoup(current_html, 'html.parser') + + # "img class='image_resized'" 태그만 추출 + resized_images = soup.find_all('img', class_='image_resized') + + # 추출된 태그들로 새로운 HTML 문자열 생성 + original_html_text = ''.join(str(tag) for tag in resized_images) + + return original_html_text def NS_info_with_HTML(products): # 상품 정보를 담을 5x1 표 생성 - product_info_text = "" + product_info_table = "
" global avg_price avg_price = 0 @@ -257,44 +267,18 @@ def NS_info_with_HTML(products): # 각 상품 카드를 생성하고 테이블의 셀로 추가 product_card = create_product_card(product["productTitle"], product["imageUrl"], formatted_price, product["rank"], product["purchase"], product["review"]) - product_info_text += f"" + product_info_table += f"" avg_price += price - product_info_text += "
{product_card}{product_card}
" + product_info_table += "" if products: avg_price = round(avg_price / len(products), 0) - product_info_text += f'

네이버 상품의 평균 가격은 {avg_price:,.0f}원입니다.

' + product_info_table += f'

네이버 상품의 평균 가격은 {avg_price:,.0f}원입니다.

' - return product_info_text + return product_info_table -#네이버쇼핑 함수 HTML -def NS_info_with_HTML_ori(products): - product_info_text = "" - global avg_price - avg_price = 0 - - for product in products: - if isinstance(product["price"], str): - price = int(product["price"].replace(",", "")) - else: - price = product["price"] - formatted_price = format(price, ",") + "원" - - # 각 상품 카드를 생성하여 테이블의 셀로 추가 - product_card = create_product_card(product["productTitle"], product["imageUrl"], formatted_price, product["rank"]) - product_info_text += f"{product_card}" - avg_price += price - - product_info_text += "" - - if products: - avg_price = round(avg_price / len(products), 0) - product_info_text += f'
네이버 상품의 평균 가격은 {avg_price}원입니다.
' - - return product_info_text - def naver_prices(products): prices = [] for product in products: @@ -337,64 +321,51 @@ def create_product_card(product_name, image_url, price, rank, purchase, review): return product_card -def create_product_card_ori(product_name, image_url, price, rank): - # 이미지 크기를 직접 지정 - html_text = f""" - - - - - - - - - - - - - - -
상품 이미지가격: {price}
순위: {rank}
{product_name}
- """ - return html_text +# #네이버쇼핑 함수 마크다운 +# def NS_info_markdown(products): +# product_info_md = "" +# global avg_price +# avg_price = 0 - -#네이버쇼핑 함수 마크다운 -def NS_info_markdown(products): - product_info_md = "" - global avg_price - avg_price = 0 - - for index, product in enumerate(products): - idx = index + 1 - # 제품명을 헤더로 표시 - product_info_md += f"### {idx}번상품. {product['productTitle']}\n" +# for index, product in enumerate(products): +# idx = index + 1 +# # 제품명을 헤더로 표시 +# product_info_md += f"### {idx}번상품. {product['productTitle']}\n" - # 이미지 추가 - product_info_md += f"![상품 이미지]({product['imageUrl']})\n\n" +# # 이미지 추가 +# product_info_md += f"![상품 이미지]({product['imageUrl']})\n\n" - # 가격과 순위 정보 - if isinstance(product["price"], str): - price = int(product["price"].replace(",", "")) # 쉼표 제거 후 정수 변환 - else: - price = product["price"] - formatted_price = format(price, ",") + "원" +# # 가격과 순위 정보 +# if isinstance(product["price"], str): +# price = int(product["price"].replace(",", "")) # 쉼표 제거 후 정수 변환 +# else: +# price = product["price"] +# formatted_price = format(price, ",") + "원" - product_info_md += f"- **가격:** {formatted_price}\n" - product_info_md += f"- **순위:** {product['rank']}\n\n" +# product_info_md += f"- **가격:** {formatted_price}\n" +# product_info_md += f"- **순위:** {product['rank']}\n\n" - avg_price += price # 평균 가격 계산을 위해 가격 추가 +# avg_price += price # 평균 가격 계산을 위해 가격 추가 - if products: # products가 비어 있지 않은 경우에만 평균 가격 계산 - avg_price = round(avg_price / len(products), 0) - product_info_md += f"**네이버 상품의 평균 가격은 {avg_price}원입니다.**\n" +# if products: # products가 비어 있지 않은 경우에만 평균 가격 계산 +# avg_price = round(avg_price / len(products), 0) +# product_info_md += f"**네이버 상품의 평균 가격은 {avg_price}원입니다.**\n" - return product_info_md +# return product_info_md -def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes): - product_title = product_info.init_title - product_low_cost = product_info.tao_low_price - product_high_cost = product_info.tao_high_price +def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes, login_info): + + detail_css = ".ant-tabs-tab:nth-child(6)" + + thumb_data_note = "5" + click_and_confirm_tab(driver, thumb_data_note, 10) + + + product_keyword = product_info.keyword_title + # product_low_cost = product_info.tao_low_price + # product_high_cost = product_info.tao_high_price + product_low_cost = product_info.option_low_price + product_high_cost = product_info.option_high_price image_src = product_info.main_image_url try: @@ -409,6 +380,30 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver logger.debug(f"카테고리 코드 검색 중 예외 발생 : {e}", exc_info=True) naver_code = "" + + + try: + logger.debug("네이버쇼핑 파싱 중") + products = parse_naver_shopping(product_keyword, naver_code, isOverseas=1, sortcount=5) + logger.debug("네이버쇼핑 파싱 완료") + # logger.debug(f"네이버 파싱된 상품 리스트 \n {products}") + product_info.naver_products = products + + # 네이버 상품가격 담기 + naver_price = naver_prices(products) + product_info.naver_low_price = naver_price[0] + product_info.naver_avg_price = naver_price[1] + product_info.naver_high_price = naver_price[2] + + # product_info_text = NS_info(products) + product_info_card = NS_info_with_HTML(products) + # logger.debug(f"수집된 정보 \n {product_info_card} \n") + logger.debug("네이버쇼핑 파싱 완료") + except Exception as e: + logger.debug(f"네이버쇼핑 파싱 중 에러발생 : {e}", exc_info=True) + + + # click_element('XPATH', '/html/body/div[7]/div/div[3]/div/div[2]/div[1]/div/div[2]/div[8]/div/div/div[2]/div[1]/div/div/span[2]/div/div') # testt = find_delivery_fee(7,delv_collection) @@ -430,8 +425,8 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver except Exception as e: logger.debug(f"상세페이지 탭으로 이동 중 오류 발생: 요소를 찾을 수 없습니다. : {e}", exc_info=True) # detail_tab = driver.find_element(By.CSS_SELECTOR, ".ant-tabs-tab:nth-child(6)") - detail_tab.click() - time.sleep(2) # 페이지 로딩 대기 + # detail_tab.click() + time.sleep(0.2) # 페이지 로딩 대기 # 상세페이지 내용 수정 try: @@ -446,11 +441,10 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver try: ActionChains(driver).move_to_element(detail_content).click().perform() time.sleep(1) - logger.debug("AI 이미지 처리중") # contents = bard_img(image_src) # contents = gemini.generate_description(image_src, product_title) - aicontents = safe_generate_content(gemini, image_src, product_title) + aicontents = safe_generate_content(gemini, product_info) logger.debug(f"{aicontents}") product_info.ai_contents = aicontents logger.debug("AI 이미지 처리 완료") @@ -467,30 +461,54 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver logger.debug(f"추가포장비 추정 : {packing_fee}") product_info.packing_fee = packing_fee - logger.debug("네이버쇼핑 파싱 중") - products = parse_naver_shopping(product_title, naver_code, isOverseas=1, sortcount=5) - - logger.debug(f"네이버 파싱된 상품 리스트 \n {products}") - product_info.naver_products = products - - # 네이버 상품가격 담기 - naver_price = naver_prices(products) - product_info.naver_low_price = naver_price[0] - product_info.naver_avg_price = naver_price[1] - product_info.naver_high_price = naver_price[2] - - # product_info_text = NS_info(products) - product_info_text = NS_info_with_HTML(products) - # logger.debug(f"수집된 정보 \n {product_info_text} \n") - logger.debug("네이버쇼핑 파싱 완료") except Exception as e: logger.debug(f"상세페이지 편집 중 에러발생 : {e}", exc_info=True) + try: + # 가격 정보 계산 + low_cost, low_margin = selling_price(product_low_cost, delv_fee, 0.29) + high_cost, high_margin = selling_price(product_high_cost, delv_fee, 0.29) + low_delv_fee = avg_price - low_cost + high_delv_fee = avg_price - high_cost + + # 마진율 계산 + low_margin_r = round((low_margin / low_cost) * 100, 2) + high_margin_r = round((high_margin / high_cost) * 100, 2) + + # 텍스트 조합 + cost_add_text = f""" +

==== 가격과 마진율 ====


+ 해당 제품의 네이버 평균가격은 {avg_price:,.0f}원입니다.
+ 해당 제품의 무게배송비는 {delv_fee:,.0f}원입니다.
+ + **마진율 확보를 위한 판매가 범위:** {low_cost:,.0f}원 ~ {high_cost:,.0f}원
+ +

**저가 중심 계산:**


+ * 무게 배송비 대비: {low_delv_fee:,.0f}원 {('낮은' if low_delv_fee < 0 else '높은')} 편
+ * 마진율: {low_margin_r:,.2f}%
+

**고가중심 계산:**


+ * 무게 배송비 대비: {high_delv_fee:,.0f}원 {('낮은' if high_delv_fee < 0 else '높은')} 편
+ * 마진율: {high_margin_r:,.2f}%
+ +

**추가 정보:**


+

* 해당 제품의 파손 여부 및 무게 오차를 고려하여 더하기 마진을 설정하세요.


+

=======================================



+ """ + + # time.sleep(2) + # detail_content.send_keys(cost_add_text) + + except Exception as e: + logger.debug(f"가격정보 생성 중 에러 : {e}", exc_info=True) + + + try: + logger.debug("HTML 수정 버튼 클릭 .") 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') + click_element(driver, 'XPATH', html_btn_xpath, 5, 'ac') # 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) @@ -498,7 +516,6 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver # ) # logger.debug("HTML 수정 버튼을 성공적으로 찾았습니다.") # html_btn.click() - logger.debug("HTML 수정 버튼 클릭 .") except Exception as e: logger.debug(f"HTML 수정 버튼 요소를 찾을 수 없습니다. : {e}", exc_info=True) @@ -507,62 +524,78 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver try: + # textarea_css = "ck-source-editing-area" + # click_element(driver, 'CSS_SELECTOR', textarea_css, 10, 'js') textarea = WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.CLASS_NAME, "ck-source-editing-area")) ) logger.debug("textarea버튼을 성공적으로 찾았습니다.") - sys.stdout.flush() - textarea.click() + time.sleep(0.2) + actions = ActionChains(driver) + actions.move_to_element(textarea).perform() # 요소로 스크롤 + logger.debug("'textarea' 요소로 스크롤 실행") + time.sleep(0.2) + actions.click(textarea).perform() + logger.debug("'textarea' 요소 클릭 실행") + + # textarea.click() except Exception as e: logger.debug(f"textarea버튼 요소를 찾을 수 없습니다. : {e}", exc_info=True) try: # # data-value 속성 값을 가져옵니다. current_value = textarea.get_attribute("data-value") + original_html_tags = original_html(current_value) # logger.debug(f"현재 속성값 :{current_value}") - product_info.current_value = current_value + product_info.current_value = original_html_tags logger.debug("현재 속성값 수집 완료") + # # ============번역을 위한 사전작업============ # 이미지 Url 수집 # translated_image_urls = [] # 번역된 이미지 URL들을 저장할 리스트 - detail_images = fetch_image_urls(current_value) - logger.debug(f"detail_images URLs \n {detail_images}") + detail_images = fetch_image_urls(original_html_tags) + # logger.debug(f"detail_images URLs \n {detail_images}") product_info.detail_image_urls = detail_images - # 원본 URL을 빈문자열로 대체 - logger.debug("원본 URL을 빈 문자열로 대체") - for original_url in detail_images: - current_value = current_value.replace(original_url, "") + # logger.debug("원본 URL을 빈 문자열로 대체") + # for original_url in detail_images: + # current_value = current_value.replace(original_url, "") + # logger.debug("새로운 data-value 값으로 설정되었습니다.") + # # ============번역을 위한 사전작업============ - - # # # 새로운 data-value 값을 생성합니다. - # new_value = product_info_text + "\n" + current_value - # # logger.debug(f"new_value \n {new_value}") - # product_info.new_value = new_value - # logger.debug("새로운 data-value 값 생성") - - # # # data-value 속성을 새로운 값으로 설정합니다. - # driver.execute_script("arguments[0].setAttribute('data-value', arguments[1]);", textarea, new_value) - - # # driver.execute_script("arguments[0].innerHTML = arguments[1]", textarea, new_value) - # time.sleep(1) - # # driver.execute_script("arguments[0].innerHTML = arguments[1]", detail_content, new_value); - - logger.debug("새로운 data-value 값으로 설정되었습니다.") - - # save_button.click() - click_element(driver, 'XPATH', save_button_xpath, 5, 'js') + logger.debug("product_info_card 결합.") + new_value = product_info_card +'

' + cost_add_text +'

' +original_html_tags + # textarea.send_keys(product_info_card) time.sleep(0.2) + logger.debug("결합.") + # 결합된 값을 다시 textarea에 설정 + try: + # # data-value 속성을 새로운 값으로 설정합니다. + driver.execute_script("arguments[0].setAttribute('data-value', arguments[1]);", textarea, new_value) + + # # driver.execute_script("arguments[0].innerHTML = arguments[1]", textarea, new_value) + # # driver.execute_script("arguments[0].innerHTML = arguments[1]", detail_content, new_value); - # textarea.send_keys(product_info_text) - # logger.debug("detail_content 전송.") + # # JavaScript를 사용하여 textarea 값 설정 + # script = "arguments[0].value = arguments[1];" + # driver.execute_script(script, textarea, new_value) + time.sleep(0.5) + logger.debug("새로운 값이 성공적으로 설정됨.") + except Exception as e: + logger.error(f"새로운 값 설정 중 오류 발생: {e}", exc_info=True) + time.sleep(0.2) + # textarea.send_keys(Keys.ENTER) # textarea.send_keys(Keys.ENTER) # logger.debug("엔터키 전송.") + click_element(driver, 'XPATH', save_button_xpath, 5, 'js') + time.sleep(0.2) + logger.debug("저장버튼 전송.") + # html_btn.click() click_element(driver, 'XPATH', html_btn_xpath, 5, 'js') @@ -588,13 +621,15 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver # contents 변수의 값이 None이 아닐 때만 send_keys 메서드를 호출합니다. if aicontents is not None: detail_content.send_keys(aicontents) + logger.debug(f"AI 컨텐츠 입력완료") + else: # contents 변수가 None일 때의 대체 처리 # 예: detail_content.send_keys("") 또는 아무 동작도 수행하지 않음 pass - + time.sleep(0.5) - + detail_content.send_keys(Keys.ENTER) detail_content.send_keys(Keys.ENTER) detail_content.send_keys(Keys.ENTER) @@ -602,94 +637,34 @@ 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) - - - logger.debug("====번역이미지 붙여넣기 완료=====") - - # 인용버튼 클릭 - # quote_button = driver.find_element(By.XPATH, "//div[@id='productMainContentContainerId']/div/div/div[2]/div[2]/div/div/div[2]/div/div/button[6]") - # quote_button = driver.find_element(By.CSS_SELECTOR, ".ck:nth-child(16)") - - # try: - # quote_button = WebDriverWait(driver, 10).until( - # EC.presence_of_element_located((By.CSS_SELECTOR, ".ck:nth-child(16)")) - # ) - # logger.debug("인용버튼을 성공적으로 찾았습니다.") - # except: - # logger.debug("인용버튼 요소를 찾을 수 없습니다.") - # quote_button.click() - # time.sleep(0.5) + 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) - try: - # 가격 정보 계산 - low_cost, low_margin = selling_price(product_low_cost, delv_fee, 0.29) - high_cost, high_margin = selling_price(product_high_cost, delv_fee, 0.29) - low_delv_fee = avg_price - low_cost - high_delv_fee = avg_price - high_cost - - # 마진율 계산 - low_margin_r = round((low_margin / low_cost) * 100, 2) - high_margin_r = round((high_margin / high_cost) * 100, 2) - - # 텍스트 조합 - add_text = f""" - ============= 가격과 마진율 ============= - 해당 제품의 네이버 평균가격은 {avg_price:,.0f}원입니다. - 해당 제품의 무게배송비는 {delv_fee:,.0f}원입니다. - - **마진율 확보를 위한 판매가 범위:** {low_cost:,.0f}원 ~ {high_cost:,.0f}원 - - **저가:** - * 무게 배송비 대비: {low_delv_fee:,.0f}원 {('낮은' if low_delv_fee < 0 else '높은')} 편 - * 마진율: {low_margin_r:,.2f}% - - **고가:** - * 무게 배송비 대비: {high_delv_fee:,.0f}원 {('낮은' if high_delv_fee < 0 else '높은')} 편 - * 마진율: {high_margin_r:,.2f}% - - **적정 배송비:** {low_delv_fee:,.0f}원 ~ {high_delv_fee:,.0f}원 - - **추가 정보:** - * 해당 제품의 파손 여부 및 무게 오차를 고려하여 더하기 마진을 설정하세요. - ======================================= - """ - - detail_content.send_keys(add_text) - time.sleep(2) - except Exception as e: - logger.debug(f"가격정보 생성 중 에러 : {e}", exc_info=True) - - # 저장 버튼 클릭 - # try: - # save_button = WebDriverWait(driver, 10).until( - # EC.presence_of_element_located((By.XPATH, "//button[contains(.,'저장하기')]")) - # ) - # logger.debug("저장 버튼을 성공적으로 찾았습니다.") - # except Exception as e: - # logger.debug(f"저장 버튼 요소를 찾을 수 없습니다. : {e}", exc_info=True) - # save_button = driver.find_element(By.XPATH, "//button[contains(.,'저장하기')]") - # save_button.click() + logger.debug("====번역이미지 붙여넣기 완료=====") + + + + logger.debug("상세페이지 편집 저장") click_element(driver, "XPATH", save_button_xpath, 5, 'js') diff --git a/edit/ns.py b/edit/ns.py new file mode 100644 index 0000000..6774185 --- /dev/null +++ b/edit/ns.py @@ -0,0 +1,188 @@ +from playwright.sync_api import sync_playwright +from bs4 import BeautifulSoup +import requests, json + +def run(playwright, keyword): + browser = playwright.chromium.launch(headless=False) # 헤드리스 모드 비활성화 + context = browser.new_context( + user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + locale="en-US", # 언어 설정 + timezone_id="America/New_York" # 시간대 설정 + ) + page = context.new_page() + + # navigator.webdriver 비활성화 + page.evaluate("navigator.webdriver = undefined") + + print("브라우저 열기 및 사용자 에이전트 설정 완료") + + page.goto(f"https://search.shopping.naver.com/search/all?query={keyword}&bt=-1&frm=NVSCPRO") + print("페이지 로딩 완료") + + # 접근 시간 지연 + page.wait_for_timeout(1000) + + print("페이지 로딩 완료") + # 페이지의 HTML 가져오기 + html = page.content() + print(html) + + soup = BeautifulSoup(html, 'html.parser') + + products = extract_product_info(soup) + + for product in products: + print(product.text) + + browser.close() + + +def extract_product_info(soup): + # 상품 정보를 담을 리스트 초기화 + product_info_list = [] + + # 각 상품에 대한 정보 추출 + products = soup.find_all('div', class_='basicList_info_area__17Xyo') + print(f"products : {products}") + for i, product in enumerate(products, 1): + # 상품명 + title = product.find('a', class_='product_link__TrAac').get('title') + print(f"{i}번째 상품 title : {title}") + + # 썸네일 URL + thumbnail_element = product.find('a', class_='thumbnail_thumb__Bxb6Z') + thumbnail_url = thumbnail_element.find('img').get('src') if thumbnail_element else None + print(f"{i}번째 상품 thumbnail_url : {thumbnail_url}") + + # 가격과 배송비 + price_area = product.find('div', class_='product_price_area__eTg7I') + price = price_area.find('span', class_='price_num__S2p_v').text.strip() if price_area else None + print(f"{i}번째 상품 price : {price}") + delivery_fee = price_area.find('span', class_='price_delivery__yw_We').text.strip() if price_area else None + print(f"{i}번째 상품 delivery_fee : {delivery_fee}") + + # 카테고리 + categories = [cat.text for cat in product.find_all('span', class_='product_category__l4FWz')] + print(f"{i}번째 상품 categories : {categories}") + + # 리뷰, 구매건수, 등록일, 찜하기 + etc_info = product.find('div', class_='product_etc_box__ElfVA') + review_count = etc_info.find('a', text='리뷰').find('em').text if etc_info and etc_info.find('a', text='리뷰') else '0' + print(f"{i}번째 상품 review_count : {review_count}") + purchase_count = etc_info.find('span', text='구매건수').find('em').text if etc_info and etc_info.find('span', text='구매건수') else '0' + print(f"{i}번째 상품 purchase_count : {purchase_count}") + registration_date = etc_info.find('span', text='등록일').text.replace('등록일 ', '') if etc_info and etc_info.find('span', text='등록일') else None + print(f"{i}번째 상품 registration_date : {registration_date}") + zzim_count = etc_info.find('a', class_='product_btn_zzim__MQ17u').find('em').text if etc_info and etc_info.find('a', class_='product_btn_zzim__MQ17u') else '0' + print(f"{i}번째 상품 zzim_count : {zzim_count}") + + # 사전에 정보 저장 + product_info = { + 'title': title, + 'thumbnail_url': thumbnail_url, + 'price': price, + 'delivery_fee': delivery_fee, + 'categories': categories, + 'review_count': review_count, + 'purchase_count': purchase_count, + 'registration_date': registration_date, + 'zzim_count': zzim_count + } + + product_info_list.append(product_info) + print(f"{i}번째 상품 정보 추가 완료") + + return product_info_list + + + +def ns(keyword): + # 네이버 쇼핑 URL 설정 + urlBase = "https://search.shopping.naver.com/search/all?query=" + # urlEnd = f"&cat_id={naver_code}&frm=NVSHATC&pagingIndex=1&pagingSize=40&&productSet=overseas&sort=rel×tamp=&viewType=list" + urlEnd = "&frm=NVSHATC&pagingIndex=1&pagingSize=40&&productSet=overseas&sort=rel×tamp=&viewType=list" + url = urlBase + keyword + urlEnd + # print(f"네이버 카테코드는 [{naver_code}] 입니다.") + print("네이버 카테코드는 [생략]] 입니다.") + print(f"대상키워드는 [{keyword}] 입니다.") + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "Accept-Language": "en-US,en;q=0.9", + "Accept-Encoding": "gzip, deflate, br", + "DNT": "1", # Do Not Track 요청 헤더 (사용자의 추적을 거부) + "Connection": "keep-alive", + "Upgrade-Insecure-Requests": "1", # https로의 업그레이드를 요청 + "Cache-Control": "max-age=0", # 캐시된 콘텐츠를 재사용하지 않도록 요청 + } + + # # 네이버 쇼핑에 접속하여 HTML 받아오기 + # response = requests.get(url, headers=headers) + # soup = BeautifulSoup(response.text, 'html.parser') + + # 네이버 쇼핑에 접속하여 HTML 받아오기 + try: + response = requests.get(url, headers=headers) + html = response.text + print(f"response : {response}") + # print(f"html : {html}") + response.raise_for_status() # 만약 요청이 실패하면 예외 발생 + soup = BeautifulSoup(response.text, 'html.parser') + next_data_str = soup.find("script", {"id": "__NEXT_DATA__"}).string + next_data_json = json.loads(next_data_str) + products_list = next_data_json["props"]["pageProps"]["initialState"]["products"]["list"] + products_info = [] + for product in products_list: + price = product.get("item", {}).get("price") + productTitle = product.get("item", {}).get("productTitle") + category1Name = product.get("item", {}).get("category1Name") + category2Name = product.get("item", {}).get("category2Name") + category3Name = product.get("item", {}).get("category3Name") + category4Name = product.get("item", {}).get("category4Name") + openDate = product.get("item", {}).get("openDate") + mallCount = product.get("item", {}).get("mallCount") + keepCnt = product.get("item", {}).get("keepCnt") + overseaTp = product.get("item", {}).get("overseaTp") + reviewCount = product.get("item", {}).get("reviewCount") + reviewCountSum = product.get("item", {}).get("reviewCountSum") + scoreInfo = product.get("item", {}).get("scoreInfo") + naverPayAdAccumulatedDisplayValue = product.get("item", {}).get("naverPayAdAccumulatedDisplayValue") + mobileLowPrice = product.get("item", {}).get("mobileLowPrice") + lowPrice = product.get("item", {}).get("lowPrice") + deliveryFeeContent = product.get("item", {}).get("deliveryFeeContent") + dlvryLowPrice = product.get("item", {}).get("dlvryLowPrice") + imageUrl = product.get("item", {}).get("imageUrl") + imgSz = product.get("item", {}).get("imgSz") + searchKeyword = product.get("item", {}).get("searchKeyword") + mallProductUrl = product.get("item", {}).get("mallProductUrl") + mallPcUrl = product.get("item", {}).get("mallPcUrl") + mallName = product.get("item", {}).get("mallName") + manuTag = product.get("item", {}).get("manuTag") + #mallInfoCache = product.get("item", {}).get("mallInfoCache") + purchaseCnt = product.get("item", {}).get("purchaseCnt") + rank = product.get("item", {}).get("rank") + + # 상품 정보를 딕셔너리로 만들어 리스트에 추가 + product_info = { + "productTitle": productTitle, + "price": price, + "imageUrl": imageUrl, + "rank": rank, + "purchase" : purchaseCnt, + "review" : reviewCountSum + } + products_info.append(product_info) + + print(f"키워드 검색 결과 상품 [{keyword}]에 대한 [{len(products_info)}]개의 상품정보수집 완료") + + print(f"products_info \n {products_info}") + except Exception as e: + print(f"Exception : {e}") + + +keywrod = "방폭등" + +ns(keywrod) + +# with sync_playwright() as playwright: +# run(playwright, keywrod) \ No newline at end of file diff --git a/edit/options.py b/edit/options.py index 405ae13..01ddea5 100644 --- a/edit/options.py +++ b/edit/options.py @@ -6,7 +6,7 @@ from selenium.webdriver.common.keys import Keys import time from edit.action_elements import click_element, return_element, click_and_confirm_tab from ai.deepl import trans -from ai.deepl_with_playwright import trans_text +from ai.deepl_with_playwright import trans_text, trans_list_text # from ai.compare import find_most_similar_image_by_one import re import logging @@ -251,31 +251,35 @@ def option_name_trans(driver, product_info, option_type_number, option_count, al ori_optionName_element = driver.find_element(By.XPATH, ori_optionName_xpath) ori_optionName = ori_optionName_element.text.strip() - - ori_optionNames.append(ori_optionName) + cleaned_ori_optionName = replace_or_remove_special_chars(ori_optionName, allowed_special_chars, special_char_replacements) + ori_optionNames.append(cleaned_ori_optionName) except Exception as e: logger.debug(f"원본옵션명 처리중 에러발생 : {e}", exc_info=True) # 원본 옵션명을 하나의 텍스트로 합치기 - combined_ori_optionNames = '\n\n'.join(ori_optionNames) + # combined_ori_optionNames = '\n\n'.join(ori_optionNames) - 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}") + # 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}") logger.debug("번역 시행") - # trans_optionNames_text = trans_text(cleaned_ori_text) # DeepL 번역 함수 - trans_optionNames_text = trans(cleaned_ori_text) # DeepL 번역 함수 + deepl_trans_optionNames = trans_list_text(ori_optionNames) # DeepL 번역 함수 + # trans_optionNames_text = trans_text(cleaned_ori_text) # DeepL_with_playwright 번역 함수 - logger.debug(f"번역된 텍스트 \n {trans_optionNames_text} ") + # trans_optionNames_text = trans(cleaned_ori_text) # DeepL 번역 함수 + + logger.debug(f"번역된 텍스트 \n {deepl_trans_optionNames} ") 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("번역 텍스트 나누기") + trans_optionNames = [] + for deepl_trans_optionName in deepl_trans_optionNames: + cleand_trans_optionName = replace_or_remove_special_chars(deepl_trans_optionName, allowed_special_chars, special_char_replacements) + trans_optionNames.append(cleand_trans_optionName) + + # trans_optionNames = trans_optionNames_text.split('\n\n') + # logger.debug("번역 텍스트 나누기") logger.debug("product_info 옵션명 업데이트") try: diff --git a/edit/price.py b/edit/price.py index 37d2c04..0ac74bd 100644 --- a/edit/price.py +++ b/edit/price.py @@ -20,116 +20,137 @@ def modify_price_page(driver, product_infos): # 가격 탭으로 이동 logger.debug("가격탭으로 이동") - option_tab_XPATH = "//div[@id='rc-tabs-0-tab-3']" - keyword_tab_CSS = ".ant-tabs-tab:nth-child(3)" - click_element(driver, 'CSS_SELECTOR', keyword_tab_CSS, 10, 'js') + # option_tab_XPATH = "//div[@id='rc-tabs-0-tab-3']" + # keyword_tab_CSS = ".ant-tabs-tab:nth-child(3)" + # click_element(driver, 'CSS_SELECTOR', keyword_tab_CSS, 10, 'js') logger.debug("가격탭으로 이동 완료") logger.debug("페이지 로딩 대기") time.sleep(2) # 페이지 로딩 대기. - option_high_price = product_infos.option_high_price - option_low_price = product_infos.option_low_price - # tao_high_price = product_infos.tao_high_price # 디버깅을 위해 선택된 옵션가격이 아닌 기존의 원래가격을 가져옴 - # tao_low_price = product_infos.tao_low_price # 디버깅을 위해 선택된 옵션가격이 아닌 기존의 원래가격을 가져옴 - - naver_low_price = product_infos.naver_low_price - naver_avg_price = product_infos.naver_avg_price - naver_high_price = product_infos.naver_high_price - w_delv_fee = product_infos.w_delv_fee - packing_fee = product_infos.packing_fee - - inputs = { - "option_low_price": option_low_price, - "option_high_price": option_high_price, - "delv_fee": w_delv_fee, - "packing_fee": packing_fee, - "ns_low_price": naver_low_price, - "ns_high_price": naver_high_price - } - logger.debug(f"가격계산 INPUT 요소 : {inputs}") + try: + option_high_price = product_infos.option_high_price + option_low_price = product_infos.option_low_price + + # tao_high_price = product_infos.tao_high_price # 디버깅을 위해 선택된 옵션가격이 아닌 기존의 원래가격을 가져옴 + # tao_low_price = product_infos.tao_low_price # 디버깅을 위해 선택된 옵션가격이 아닌 기존의 원래가격을 가져옴 + + naver_low_price = product_infos.naver_low_price + naver_avg_price = product_infos.naver_avg_price + naver_high_price = product_infos.naver_high_price + w_delv_fee = product_infos.w_delv_fee + packing_fee = product_infos.packing_fee + + inputs = { + "option_low_price": option_low_price, + "option_high_price": option_high_price, + "delv_fee": w_delv_fee, + "packing_fee": packing_fee, + "ns_low_price": naver_low_price, + "ns_high_price": naver_high_price + } + logger.debug(f"가격계산 INPUT 요소 : {inputs}") + except Exception as e: + logger.error(f"가격계산 INPUT 요소 계산 중 에러 발생 {e}", exc_info=True) - - outputs = calculate_margin_and_price(inputs) - logger.debug(f"가격계산 OUTPUT 요소 : {outputs}") - - selling_price = outputs["selling_price"] - final_margin_rate = outputs["final_margin_rate"] - seller_cost = outputs["seller_cost"] - plus_margin = outputs["plus_margin"] - ns_avg_price = outputs["ns_avg_price"] - - return_fee = selling_price/2 - - init_delv_fee = seller_cost - exchange_fee = return_fee + init_delv_fee + try: + outputs = calculate_margin_and_price(inputs) + logger.debug(f"가격계산 OUTPUT 요소 : {outputs}") + + selling_price = outputs["selling_price"] + final_margin_rate = outputs["final_margin_rate"] + seller_cost = outputs["seller_cost"] + plus_margin = outputs["plus_margin"] + ns_avg_price = outputs["ns_avg_price"] + + return_fee = round((selling_price*0.4) / 1000) * 1000 + + init_delv_fee = seller_cost + exchange_fee = return_fee + init_delv_fee - product_infos.plus_fee = plus_margin - product_infos.return_fee = return_fee - product_infos.init_delv_fee = init_delv_fee - product_infos.exchange_fee = exchange_fee + product_infos.plus_fee = plus_margin + product_infos.return_fee = return_fee + product_infos.init_delv_fee = init_delv_fee + product_infos.exchange_fee = exchange_fee + + logger.debug(f"결정된 상품가격: {selling_price}원, 최종 마진율: {final_margin_rate:.2f}%") + logger.debug(f"판매자 원가: {seller_cost}원") + logger.debug(f"더하기 마진: {plus_margin}원") + logger.debug(f"네이버 평균가: {ns_avg_price}원") + except Exception as e: + logger.error(f"가격계산 OUTPUT 요소 계산 중 에러 발생 {e}", exc_info=True) - print(f"결정된 상품가격: {selling_price}원, 최종 마진율: {final_margin_rate:.2f}%") - print(f"판매자 원가: {seller_cost}원") - print(f"더하기 마진: {plus_margin}원") - print(f"네이버 평균가: {ns_avg_price}원") - - # 가격 탭으로 이동 - logger.debug("내부함수 가격 탭으로 이동") - thumb_tab_CSS = '.ant-tabs-tab:nth-child(3)' - click_element(driver, 'CSS_SELECTOR', thumb_tab_CSS, 10, 'js') - logger.debug("내부함수 가격 탭으로 이동 완료") - logger.debug("페이지 로딩 대기") - time.sleep(2) # 페이지 로딩 대기. + # # 가격 탭으로 이동 + # logger.debug("내부함수 가격 탭으로 이동") + # thumb_tab_CSS = '.ant-tabs-tab:nth-child(3)' + # click_element(driver, 'CSS_SELECTOR', thumb_tab_CSS, 10, 'js') + # logger.debug("내부함수 가격 탭으로 이동 완료") + # logger.debug("페이지 로딩 대기") + # time.sleep(2) # 페이지 로딩 대기. - logger.debug("더하기마진 수정") - plus_fee_xpath="//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/div/div[8]/div/div/div[3]/div/div/div/div/div[2]/input" - plus_fee_element = return_element(driver, 'XPATH', plus_fee_xpath, 10) - plus_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 - driver.execute_script("arguments[0].value = '';", plus_fee_element) # 기존 가격 삭제 JS - logger.debug("기존가격 삭제") - plus_fee_element.send_keys(plus_margin) # 새 가격 입력 - logger.debug(f"더하기마진 수정 완료 : {plus_margin}") - - logger.debug("해외배송비 수정") - fore_delv_fee_xpath="//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/div/div[10]/div/div/div/div/div[2]/input" - fore_delv_fee_element = return_element(driver, 'XPATH', fore_delv_fee_xpath, 10) - fore_delv_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 - driver.execute_script("arguments[0].value = '';", fore_delv_fee_element) # 기존 가격 삭제 JS - logger.debug("기존가격 삭제") - fore_delv_fee_element.send_keys(w_delv_fee) # 새 가격 입력 - logger.debug(f"해외배송비 수정 완료 : {w_delv_fee}") - - logger.debug("반품비 수정") - return_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[3]/div/div/div/div/div[2]/input" - return_fee_element = return_element(driver, 'XPATH', return_fee_xpath, 10) - return_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 - driver.execute_script("arguments[0].value = '';", return_fee_element) # 기존 가격 삭제 JS - logger.debug("기존가격 삭제") - return_fee_element.send_keys(return_fee) # 새 가격 입력 - logger.debug(f"반품비 수정 완료 : {return_fee}") - - logger.debug("초도배송비 수정") - first_delv_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[4]/div/div[2]/div/div/div[2]/input" - first_delv_fee_element = return_element(driver, 'XPATH', first_delv_fee_xpath, 10) - first_delv_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 - driver.execute_script("arguments[0].value = '';", first_delv_fee_element) # 기존 가격 삭제 JS - logger.debug("기존가격 삭제") - first_delv_fee_element.send_keys(init_delv_fee) # 새 가격 입력 - logger.debug(f"초도배송비 수정 완료 : {init_delv_fee}") - - logger.debug("교환비 수정") - exchange_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[5]/div/div/div/div/div[2]/input" - exchange_fee_element = return_element(driver, 'XPATH', exchange_fee_xpath, 10) - exchange_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 - driver.execute_script("arguments[0].value = '';", exchange_fee_element) # 기존 가격 삭제 JS - logger.debug("기존가격 삭제") - exchange_fee_element.send_keys(exchange_fee) # 새 가격 입력 - logger.debug(f"교환비 수정 완료 : {exchange_fee}") + try: + logger.debug("더하기마진 수정") + plus_fee_xpath="//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/div/div[8]/div/div/div[3]/div/div/div/div/div[2]/input" + plus_fee_element = return_element(driver, 'XPATH', plus_fee_xpath, 10) + plus_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 + driver.execute_script("arguments[0].value = '';", plus_fee_element) # 기존 가격 삭제 JS + logger.debug("기존가격 삭제") + plus_fee_element.send_keys(plus_margin) # 새 가격 입력 + logger.debug(f"더하기마진 수정 완료 : {plus_margin}") + except Exception as e: + logger.error(f"더하기마진 수정 중 에러 발생 {e}", exc_info=True) + try: + logger.debug("해외배송비 수정") + fore_delv_fee_xpath="//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/div/div[10]/div/div/div/div/div[2]/input" + fore_delv_fee_element = return_element(driver, 'XPATH', fore_delv_fee_xpath, 10) + fore_delv_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 + driver.execute_script("arguments[0].value = '';", fore_delv_fee_element) # 기존 가격 삭제 JS + logger.debug("기존가격 삭제") + fore_delv_fee_element.send_keys(w_delv_fee) # 새 가격 입력 + logger.debug(f"해외배송비 수정 완료 : {w_delv_fee}") + except Exception as e: + logger.error(f"해외배송비 수정 중 에러 발생 {e}", exc_info=True) + + try: + logger.debug("반품비 수정") + return_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[3]/div/div/div/div/div[2]/input" + return_fee_element = return_element(driver, 'XPATH', return_fee_xpath, 10) + return_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 + driver.execute_script("arguments[0].value = '';", return_fee_element) # 기존 가격 삭제 JS + logger.debug("기존가격 삭제") + return_fee_element.send_keys(return_fee) # 새 가격 입력 + logger.debug(f"반품비 수정 완료 : {return_fee}") + except Exception as e: + logger.error(f"반품비 수정 중 에러 발생 {e}", exc_info=True) + + try: + logger.debug("초도배송비 수정") + first_delv_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[4]/div/div[2]/div/div/div[2]/input" + first_delv_fee_element = return_element(driver, 'XPATH', first_delv_fee_xpath, 10) + first_delv_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 + driver.execute_script("arguments[0].value = '';", first_delv_fee_element) # 기존 가격 삭제 JS + logger.debug("기존가격 삭제") + first_delv_fee_element.send_keys(init_delv_fee) # 새 가격 입력 + logger.debug(f"초도배송비 수정 완료 : {init_delv_fee}") + except Exception as e: + logger.error(f"초도배송비 수정 중 에러 발생 {e}", exc_info=True) + + try: + logger.debug("교환비 수정") + exchange_fee_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[4]/div/div/div[5]/div/div/div/div/div[2]/input" + exchange_fee_element = return_element(driver, 'XPATH', exchange_fee_xpath, 10) + exchange_fee_element.send_keys(Keys.CLEAR) # 기존 가격 삭제 + driver.execute_script("arguments[0].value = '';", exchange_fee_element) # 기존 가격 삭제 JS + logger.debug("기존가격 삭제") + exchange_fee_element.send_keys(exchange_fee) # 새 가격 입력 + logger.debug(f"교환비 수정 완료 : {exchange_fee}`") + except Exception as e: + logger.error(f"교환비 수정 중 에러 발생 {e}", exc_info=True) + # logger.debug("기본마진율 수정") # earning_rate_xpath = "//div[@id='productMainContentContainerId']/div/div/div/div/div[2]/div/div/div[8]/div/div/div/div/div/div/div/div[2]/input" # earning_rate_element = return_element(driver, 'XPATH', earning_rate_xpath, 10, 'js') @@ -142,6 +163,9 @@ def modify_price_page(driver, product_infos): # 백그라운드 컬러로 빨간 가격탭 찾기 # background: rgb(255, 77, 79); box-shadow: none; color: rgb(255, 255, 255); - save_xpath="//button[contains(.,'저장하기')]" - click_element(driver, 'XPATH', save_xpath, 10) - logger.debug("옵션 정리 후 저장버튼 클릭 완료") + try: + save_xpath="//button[contains(.,'저장하기')]" + click_element(driver, 'XPATH', save_xpath, 10) + logger.debug("가격 정리 후 저장버튼 클릭 완료") + except Exception as e: + logger.error(f"가격 정리 저장버튼 클릭 중 에러 발생 {e}", exc_info=True) \ No newline at end of file diff --git a/edit/price_cal.py b/edit/price_cal.py index 51a0a13..743cab9 100644 --- a/edit/price_cal.py +++ b/edit/price_cal.py @@ -16,12 +16,14 @@ def calculate_margin_and_price(inputs): plus_margin = 5000 # 기본값 # 계산 로직 - ns_avg_price = (ns_low_price + ns_high_price) / 2 + ns_avg_price = round(((ns_low_price + ns_high_price) / 2) / 100) * 100 logger.debug(f"ns_avg_price : {ns_avg_price}") - option_avg_price = (option_low_price + option_high_price) / 2 + option_avg_price = round(((option_low_price + option_high_price) / 2) / 100) * 100 logger.debug(f"option_avg_price : {option_avg_price}") - tao_cost = lambda price: price * 190 * 1.035 - base_margin = lambda cost: cost * 0.12 + # tao_cost = lambda price: price * 190 * 1.035 + tao_cost = lambda price: round(price * 1.035 / 100) * 100 + base_margin = lambda cost: round(cost * 0.12 / 100) * 100 + def adjust_plus_margin_for_min_margin(seller_cost, mall_cost, selling_price): nonlocal plus_margin @@ -32,16 +34,18 @@ def calculate_margin_and_price(inputs): if final_margin_rate < target_margin_rate: plus_margin += 100 # 더하기 마진 증가 selling_price = seller_cost + plus_margin + mall_cost - mall_cost = selling_price * 0.13 + mall_cost = round(selling_price * 0.13 / 100) * 100 else: break + + logger.debug(f"final_margin_rate : {final_margin_rate}") return selling_price, final_margin_rate seller_cost = tao_cost(option_avg_price) + delv_fee + packing_fee logger.debug(f"seller_cost : {seller_cost}") - mall_cost = seller_cost * 0.13 + mall_cost = round((seller_cost * 0.13)/100) * 100 selling_price = seller_cost + plus_margin + mall_cost selling_price, final_margin_rate = adjust_plus_margin_for_min_margin(seller_cost, mall_cost, selling_price) diff --git a/img_trans/image_trans.py b/img_trans/image_trans.py index 936874c..b492ac3 100644 --- a/img_trans/image_trans.py +++ b/img_trans/image_trans.py @@ -68,8 +68,10 @@ 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) + logger.debug(f"DEEPL 번역시작") + translated_texts = translate_texts_deepl(texts_to_translate) if not translated_texts: # 빈 리스트 체크 + logger.debug(f"DEEPL 번역실패로 translatepy 시작") 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) diff --git a/img_trans/src/translation.py b/img_trans/src/translation.py index ad49aa1..f7eebaa 100644 --- a/img_trans/src/translation.py +++ b/img_trans/src/translation.py @@ -1,6 +1,7 @@ from googletrans import Translator # from img_trans.src.deepl_ori import trans from ai.deepl import trans +from ai.deepl_with_playwright import trans_list_text, trans_text from translatepy import Translator import logging @@ -21,7 +22,7 @@ def translate_texts_google(texts, src_lang='zh-cn', dest_lang='ko'): return translated_texts -def translate_texts_deepl(texts): +def translate_texts_deepl_ori(texts): """텍스트 리스트를 지정된 언어에서 다른 언어로 번역""" # 텍스트 리스트를 엔터로 구분된 하나의 문자열로 합침 combined_text = "\n".join(texts) @@ -29,18 +30,34 @@ def translate_texts_deepl(texts): # DeepL로 전체 텍스트 번역 try: - translated_combined_text = trans(combined_text) + # translated_combined_text = trans(combined_text) + translated_combined_text = trans_list_text(combined_text) for translation in translated_combined_text: # "가격"이 포함된 경우 빈 문자열로 대체 translated_texts.append(translation.text if "가격" not in translation.text else "") # 번역된 전체 텍스트를 엔터를 기준으로 분리하여 리스트로 만듦 translated_texts = translated_combined_text.split("\n") except AttributeError as e: - logger.error(f"번역 실패: {e}") + logger.error(f"번역 실패: {e}", exc_info=True) translated_texts = [] return translated_texts +def translate_texts_deepl(texts): + """텍스트 리스트를 지정된 언어에서 다른 언어로 번역""" + translated_texts = [] + + # DeepL로 전체 텍스트 번역 + try: + translated_texts = trans_list_text(texts) + # "가격"이 포함된 경우 빈 문자열로 대체 + translated_texts = [text if "가격" not in text else "" for text in translated_texts] + + except AttributeError as e: + logger.error(f"번역 실패: {e}", exc_info=True) + translated_texts = [] + + return translated_texts def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'): """translatepy 라이브러리를 사용하여 텍스트 리스트를 번역합니다.""" diff --git a/login_widget.py b/login_widget.py index 06336f5..ec06f21 100644 --- a/login_widget.py +++ b/login_widget.py @@ -51,7 +51,7 @@ class LoginWidget(QtWidgets.QWidget): # self.setGeometry(780, 420, 240, 200) # 위젯의 크기를 설정합니다. - self.resize(800, 800) + self.resize(400, 600) self.center() # 화면 가운데에 위치시키는 메서드 # 레이아웃 설정 @@ -124,6 +124,10 @@ class LoginWidget(QtWidgets.QWidget): self.loginButton = QtWidgets.QPushButton("로그인") self.loginButton.clicked.connect(self.login) + + self.DeleteDB_by_ID = QtWidgets.QLineEdit() + self.DeleteDB_by_ID.setPlaceholderText("상품ID 입력시 해당 DB 삭제") + self.alwaysOnTopSwitch = ToggleSwitch(self) self.alwaysOnTopSwitch.move(10, 10) @@ -220,13 +224,13 @@ class LoginWidget(QtWidgets.QWidget): # 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.modifyProductOptionsSwitch_layout) setting_layout.addLayout(self.modifyProductDetailSwitch_layout) setting_layout.addLayout(self.modifyImageTranslationSwitch_layout) + setting_layout.addLayout(self.modifyProductPriceSwitch_layout) + setting_layout.addLayout(self.modifyProductNameSwitch_layout) setting_layout.addLayout(self.uploadToMarketSwitch_layout) setting_layout.addLayout(self.alwaysOnTopSwitch_layout) setting_layout.addLayout(self.shutdownSwitch_layout) diff --git a/main.py b/main.py index d4b3e3a..2f71135 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service #웨일 # from webdriver_manager.chrome import ChromeDriverManager #웨일 import time -import datetime +from datetime import datetime import ctypes import atexit import platform, os, sys @@ -39,7 +39,7 @@ def prevent_sleep_mode(): ES_CONTINUOUS | ES_SYSTEM_REQUIRED ) - + # 시스템 절전 모드 방지 해제 def restore_sleep_mode(): ES_CONTINUOUS = 0x80000000 @@ -114,7 +114,10 @@ def DB_setting(): "whether_uploadToMarket": login_widget.whether_uploadToMarket, "login_result": login_widget.result, } - + + tag = login_info["whether_modifyImageTanslation"] + + logger.debug(f"whether_modifyImageTanslation : {tag}") return login_info, result, mongo_config def main(): @@ -127,7 +130,7 @@ def main(): atexit.register(restore_sleep_mode) atexit.register(record_logout_time) - if login_info.whether_shutdownAfterComplete: + if login_info["whether_shutdownAfterComplete"]: atexit.register(shutdown_system) atexit.register(send_exit_message) diff --git a/modify_products.py b/modify_products.py index 02ede56..ba26910 100644 --- a/modify_products.py +++ b/modify_products.py @@ -181,6 +181,18 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify): logger.debug(f"{current_page}페이지-{i}번 상품 수정시작") product_infos.append(ProductInfo()) # 1번 상품과 나머지 상품들에 대한 XPATH 처리 + + # 상품 수정 관련 작업을 조건에 따라 수행하는 로직 + 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"], + } steps_and_actions = [ ('tag_modification', edit_tag, (driver, product_infos[i-1])), @@ -189,21 +201,10 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify): ('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])), + # ('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: diff --git a/naver_search.py b/naver_search.py index 2977edf..fc854f0 100644 --- a/naver_search.py +++ b/naver_search.py @@ -56,11 +56,11 @@ def parse_naver_shopping(keyword, naver_code, isOverseas=1, sortcount=10): logger.debug("NEXT_DATA JSON을 파싱하는 중 오류 발생:", e) # 예외 처리 코드 추가 - # "__NEXT_DATA__" 파싱하기 - logger.debug("NEXT_DATA 파싱 완료") + # # "__NEXT_DATA__" 파싱하기 + # logger.debug("NEXT_DATA 파싱 완료") - next_data_str = soup.find("script", {"id": "__NEXT_DATA__"}).string - next_data_json = json.loads(next_data_str) + # next_data_str = soup.find("script", {"id": "__NEXT_DATA__"}).string + # next_data_json = json.loads(next_data_str) # products 리스트 가져오기 logger.debug("products 리스트 가져오기")