Compare commits

...

11 Commits

Author SHA1 Message Date
R5600U_PC 5e7b430689 카피맨 카테고리 비어있는 부분 처리 2024-06-03 07:37:52 +09:00
Envy_PC 06c01c6d90 타오파서 대폭수정. 2024-04-29 21:51:17 +09:00
Envy_PC 844366938d 캡차 세분류, log함수 잘못된 사용 수정 2024-04-28 18:29:26 +09:00
Envy_PC c856ce4045 merged_price 표시되게 수정 2024-04-22 12:09:30 +09:00
Envy_PC e5e153777e 엑셀파일 저장 시 카피맨,소싱맨은 해당가격을,
키워드소싱은 평균가격을 플로스피로 입력.
배송비는 0원처리.
2024-04-22 12:03:32 +09:00
Envy_PC af186266b3 소싱맨 카피맨처럼 가격을 미리 가져올 경우 해당 가격에서2%내린 가격으로 등록 및 배송비 0원 처리 2024-04-22 11:48:54 +09:00
Envy_PC d10feb6069 캡차방식 세분화(스크래치와 슬라이드) 2024-04-22 11:16:37 +09:00
Envy_PC 5f530fa0c1 Qtableview 업데이트
셀 직접수정 구현했으나 DB업데이트 동작하지않음.
추후업데이트 필요
2024-04-20 00:05:30 +09:00
Envy_PC 25e4f1643f Qtable에 정렬기능 추가 2024-04-19 21:57:02 +09:00
Envy_PC e5c16c42cd automatch_tao 수정사항
index = 0 일 경우 "-"가 아니라는 and 조건 추가
crop_n_rotate 수정사항
Pil 이미지 처리 후 Pil로 반환
tao_parser 수정사항
crop_n_rotate반영
2024-04-19 21:31:09 +09:00
Envy_PC 2065aa13ac 이미지크롭 추가(아직구현X)
카피맨,소싱맨 카테고리 분리코드 추가(r'>|-')
2024-04-19 20:57:06 +09:00
11 changed files with 1235 additions and 977 deletions

View File

@ -82,6 +82,7 @@ def create_db(db_name):
tao_imageUrl TEXT,
tao_itemID INTEGER,
tao_localimage TEXT,
merged_price INTEGER,
unique_id TEXT,
date_created TEXT DEFAULT (DATE('now', 'localtime')),
time_created TEXT DEFAULT (TIME('now', 'localtime')),

View File

@ -95,7 +95,6 @@ def automatch(db, item_count, message_controller, sort_order, progress_callback=
for i, product in enumerate(products):
logger.debug(f"{i}번째 product 정보 DB 업데이트 준비")
itemUrl, itemID, imageUrl, item_name, price, sales_volume = product
# DB에 상품 정보 업데이트
update_query = """
INSERT INTO Taobao (keyword_id, itemUrl, itemID, imageUrl, item_name, price, sales_volume)
@ -105,7 +104,7 @@ def automatch(db, item_count, message_controller, sort_order, progress_callback=
cursor.execute(update_query, (keyword_id, itemUrl, itemID, imageUrl, item_name, price, sales_volume))
logger.debug(f"TaoBao 테이블에 [{product}/{len(products)}] 내용 업데이트 실행")
except Exception as e:
logger.debug(f"product 정보 DB 업데이트 중 오류 발생 : {e}")
logger.debug(f"product 정보 DB 업데이트 중 오류 발생 : {e}", exc_info=True)
logger.debug(f"{len(products)}개의 product 정보 DB 업데이트 완료")
@ -120,7 +119,19 @@ def automatch(db, item_count, message_controller, sort_order, progress_callback=
# for index, (row, product) in enumerate(zip(group.iterrows(), products[:product_count])):
for index, (row, product) in enumerate(zip(group.itertuples(index=False), products[:product_count])):
itemUrl, itemID, imageUrl, item_name, price, sales_volume = product
# itemUrl, itemID, imageUrl, item_name, price, sales_volume = product # 튜플일때
# 상품 정보 추출 #리스트일때
itemUrl = product['Product URL']
itemID = product['Tao_itemID']
imageUrl = product['Image URL']
item_name = product['Product Name']
price = product['Price']
sales_volume = product['Sales Volume']
if price == '' and itemID =='':
continue
if keyword_id != row.keyword_id:
continue
@ -154,7 +165,7 @@ def automatch(db, item_count, message_controller, sort_order, progress_callback=
# PC 주소 생성
match = re.search(r'taobao.com/i(\d{10,12})', itemUrl)
pc_url = f"https://item.taobao.com/item.htm?id={match.group(1)}" if match else ""
# NaverShopping 테이블에 매칭 정보 업데이트
update_ns_query = """
UPDATE NaverShopping
@ -162,7 +173,7 @@ def automatch(db, item_count, message_controller, sort_order, progress_callback=
WHERE id = ?
"""
if index == 0:
if row.keyword != "-" and index == 0:
logger.debug(f"첫 번째 상품 업데이트 실행: {row.keyword}")
cursor.execute(update_ns_query, (final_category, delvFee, packingFee, plusFee, pc_url, imageUrl, itemID, ns_id))
conn.commit()

View File

@ -37,30 +37,25 @@ def load_cookies(driver):
logger.debug(f"쿠키 로드 중 기타 에러 발생 : {e}")
return False
def check_login_status_ori(driver):
# 로그인되지 않은 상태의 XPath
not_logged_in_xpath = "//li[@id='J_SiteNavLogin']/div/div/a"
# 로그인된 상태의 XPath
# logged_in_xpath = "//li[@id='J_SiteNavLogin']/div/div[2]/a"
def check_login_status_by_iframe(driver):
logged_in_xpath = "/html/body/div[1]/div/ul[1]/li[2]/div[1]/div[2]/a"
# # 로그인되지 않은 상태 확인
# if WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, not_logged_in_xpath))):
# logger.debug("로그인되지 않았습니다. 로그인이 필요합니다.")
# return False
logger.debug("로그인된 상태 확인")
# 로그인된 상태 확인
if WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.XPATH, logged_in_xpath))):
user_id_text = driver.find_element(By.XPATH, logged_in_xpath).text
logger.debug(f"로그인된 상태입니다. 로그인된 ID: {user_id_text}")
return True
# 로그인되지 않은 상태 확인
elif WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.XPATH, not_logged_in_xpath))):
logger.debug("로그인되지 않았습니다. 로그인이 필요합니다.")
return False
else:
logger.debug("로그인 상태를 확인할 수 없습니다.")
return False
while True:
try:
logger.debug("로그인된 상태 확인 중...")
# 로그인된 상태 확인
if driver.find_element(By.XPATH, logged_in_xpath):
user_id_text = driver.find_element(By.XPATH, logged_in_xpath).text
logger.debug(f"로그인된 상태입니다. 로그인된 ID: {user_id_text}")
return True
except:
# 로그인되지 않은 상태 확인
try:
logger.debug("로그인되지 않았습니다. 로그인이 필요합니다.")
time.sleep(5) # 5초 후 다시 체크
except:
logger.debug("로그인 상태를 확인할 수 없습니다. 잠시 후 다시 시도합니다.")
time.sleep(5) # 예외 발생 시 5초 대기 후 재시도
def check_login_status(driver):

75
modules/crop_n_rotate.py Normal file
View File

@ -0,0 +1,75 @@
import cv2
import numpy as np
from PIL import Image
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
def pil_to_cv(image_pil):
try:
"""PIL 이미지를 OpenCV 이미지(numpy array)로 변환"""
image_np = np.array(image_pil)
# Convert RGB to BGR
return image_np[:, :, ::-1]
except Exception as e:
logger.error(f"pil_to_cv 처리 중 에러 발생 : {e}")
return image_pil
def cv_to_pil(image_cv):
try:
"""OpenCV 이미지(numpy array)를 PIL 이미지로 변환"""
# Convert BGR to RGB
return Image.fromarray(image_cv[:, :, ::-1])
except Exception as e:
logger.error(f"cv_to_pil 처리 중 에러 발생 : {e}")
return image_cv
def crop_by_boxline(image_pil, crop_percent):
try:
image_cv = pil_to_cv(image_pil)
height, width = image_cv.shape[:2]
crop_height = int(height * crop_percent)
crop_width = int(width * crop_percent)
start_row, start_col = crop_height // 2, crop_width // 2
end_row, end_col = height - start_row, width - start_col
cropped_image_cv = image_cv[start_row:end_row, start_col:end_col]
return cv_to_pil(cropped_image_cv)
except Exception as e:
logger.error(f"crop_by_boxline 처리 중 에러 발생 : {e}")
return image_pil
def rotate_by_angle(image_pil, angle, color):
try:
image_cv = pil_to_cv(image_pil)
height, width = image_cv.shape[:2]
center = (width // 2, height // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
if color == "white":
rotated_image_cv = cv2.warpAffine(image_cv, rotation_matrix, (width, height), borderValue=(255, 255, 255))
elif color == "transparent":
rotated_image_cv = cv2.warpAffine(image_cv, rotation_matrix, (width, height), borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0))
return cv_to_pil(rotated_image_cv)
except Exception as e:
logger.error(f"rotate_by_angle 처리 중 에러 발생 : {e}")
return image_pil
def mirror_by_image(image_pil):
try:
image_cv = pil_to_cv(image_pil)
flipped_image_cv = cv2.flip(image_cv, 1)
return cv_to_pil(flipped_image_cv)
except Exception as e:
logger.error(f"mirror_by_image 처리 중 에러 발생 : {e}")
return image_pil
def flip_and_rotate_image(image_pil):
try:
cropped_image_pil = crop_by_boxline(image_pil, crop_percent=0.05)
mirror_image_pil = mirror_by_image(cropped_image_pil)
rotated_image_pil = rotate_by_angle(mirror_image_pil, angle=7, color="white")
return rotated_image_pil
except Exception as e:
logger.error(f"flip_and_rotate_image 처리 중 에러 발생 : {e}")
return image_pil

File diff suppressed because it is too large Load Diff

View File

@ -151,8 +151,18 @@ def parse_naver_shopping(keyword_id, keyword, isBranch, branchCount, json_data,
final_top_5_products = top5_products[:5]
logger.debug(f"RANK 정렬상품 중 마지막으로 상위 제품 [{len(final_top_5_products)}]개 선택")
merged_price = 0
for index, product in enumerate(final_top_5_products):
price = int(product.get("item", {}).get("price"))
merged_price += price # 평균 가격 계산을 위해
merged_price = merged_price / len(final_top_5_products)
c = conn.cursor()
# original relatedTags 리스트 가져오기
related_tags_ori = next_data_json["props"]["pageProps"]["relatedTags"]
@ -245,8 +255,8 @@ def parse_naver_shopping(keyword_id, keyword, isBranch, branchCount, json_data,
if count == 0:
# 중복되는 데이터가 없으면 새로운 데이터 삽입
c.execute("INSERT INTO NaverShopping (keyword_id, keyword, price, productTitle, category1Name, category2Name, category3Name, category4Name, cat_code, openDate, mallCount, keepCnt, overseaTp, reviewCount, reviewCountSum, scoreInfo, naverPayAdAccumulatedDisplayValue, mobileLowPrice, lowPrice, deliveryFeeContent, dlvryLowPrice, imageUrl, imgSz, searchKeyword, mallProductUrl, mallPcUrl, mallName, manuTag, purchaseCnt, relatedTags, rank, unique_id, date_created, time_created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(keyword_id+1, current_keyword, price, productTitle, category1Name, category2Name, category3Name, category4Name, cat_code, openDate, mallCount, keepCnt, overseaTp, reviewCount, reviewCountSum, scoreInfo, naverPayAdAccumulatedDisplayValue, mobileLowPrice, lowPrice, deliveryFeeContent, dlvryLowPrice, imageUrl, imgSz, searchKeyword, mallProductUrl, mallPcUrl, mallName, manuTag, purchaseCnt, current_keyword, rank, unique_id, date_created, time_created)) # keyword_id, item_name, price, purchase_count, related_keywords, rank는 적절하게 설정해야 합니다.
c.execute("INSERT INTO NaverShopping (keyword_id, keyword, price, productTitle, category1Name, category2Name, category3Name, category4Name, cat_code, openDate, mallCount, keepCnt, overseaTp, reviewCount, reviewCountSum, scoreInfo, naverPayAdAccumulatedDisplayValue, mobileLowPrice, lowPrice, deliveryFeeContent, dlvryLowPrice, imageUrl, imgSz, searchKeyword, mallProductUrl, mallPcUrl, mallName, manuTag, purchaseCnt, relatedTags, rank, merged_price, unique_id, date_created, time_created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(keyword_id+1, current_keyword, price, productTitle, category1Name, category2Name, category3Name, category4Name, cat_code, openDate, mallCount, keepCnt, overseaTp, reviewCount, reviewCountSum, scoreInfo, naverPayAdAccumulatedDisplayValue, mobileLowPrice, lowPrice, deliveryFeeContent, dlvryLowPrice, imageUrl, imgSz, searchKeyword, mallProductUrl, mallPcUrl, mallName, manuTag, purchaseCnt, current_keyword, rank, merged_price, unique_id, date_created, time_created)) # keyword_id, item_name, price, purchase_count, related_keywords, rank는 적절하게 설정해야 합니다.
logger.debug(f"{current_keyword} DB업데이트 완료")
else:
# 중복되는 데이터가 있으면 업데이트 또는 무시 (여기서는 예시로 업데이트 로직을 추가함)
@ -259,4 +269,5 @@ def parse_naver_shopping(keyword_id, keyword, isBranch, branchCount, json_data,
logger.debug(f"키워드 검색 결과 상품 [{keyword}]에 대한 [{len(final_top_5_products)}]개의 상품정보수집 완료")
conn.commit() # Commit the transaction
#conn.close() # Close the connection

View File

@ -48,6 +48,33 @@
<height>451</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerItem</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
</widget>
<widget class="QLineEdit" name="overPrice">
<property name="geometry">
@ -133,7 +160,7 @@
열기</string>
</property>
</widget>
<widget class="QPushButton" name="export_btn">
<widget class="QPushButton" name="export_btn_by_branch">
<property name="geometry">
<rect>
<x>360</x>
@ -287,7 +314,7 @@ XLS저장</string>
<string>Save Image</string>
</property>
</widget>
<widget class="QPushButton" name="export_btn_by_auto">
<widget class="QPushButton" name="export_btn_by_main">
<property name="geometry">
<rect>
<x>360</x>
@ -337,6 +364,27 @@ font: 75 10pt &quot;Cafe24&quot;</string>
<height>231</height>
</rect>
</property>
<property name="font">
<font>
<family>굴림</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="autoFormatting">
<set>QTextEdit::AutoAll</set>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox">

Binary file not shown.

View File

@ -32,6 +32,6 @@ class TaoScrapingThread(QThread):
logger.debug("Automatch 작업 완료")
except Exception as e:
logger.error(f"Automatch 스레드에서 오류 발생: {e}")
logger.error(f"Automatch 스레드에서 오류 발생: {e}", exc_info=True)
finally:
self.finished.emit()

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 130 KiB