업데이트
This commit is contained in:
parent
3059ba375c
commit
e806dc0538
131
main.py
131
main.py
|
|
@ -3,6 +3,8 @@ import subprocess
|
|||
import json
|
||||
from datetime import datetime, time
|
||||
from src.version import __version__
|
||||
import xlrd
|
||||
from PySide6.QtGui import QIcon
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
|
@ -295,6 +297,11 @@ class MainWindow(QMainWindow):
|
|||
self.db_input_button.setToolTip("엑셀 파일을 선택하여 DB에 저장합니다. 기존 DB를 제거하거나 추가로 데이터를 입력할 수 있습니다.")
|
||||
self.db_input_button.clicked.connect(self.load_excel)
|
||||
|
||||
# DB 양식보기 버튼
|
||||
self.sample_excel_button = QPushButton("추가양식 보기")
|
||||
self.sample_excel_button.setToolTip("추가 양식을 확인합니다.")
|
||||
self.sample_excel_button.clicked.connect(self.load_sample_excel)
|
||||
|
||||
# 기존 DB 제거 체크박스
|
||||
self.remove_db_checkbox = QCheckBox("기존 DB 제거")
|
||||
self.remove_db_checkbox.setToolTip("체크하면 기존 DB를 삭제하고 새롭게 데이터를 입력합니다.")
|
||||
|
|
@ -413,6 +420,7 @@ class MainWindow(QMainWindow):
|
|||
self.browser_selection_layout.addWidget(self.whale_path_button)
|
||||
|
||||
self.buttons_layout.addWidget(self.db_input_button)
|
||||
self.buttons_layout.addWidget(self.sample_excel_button) # 추가 양식 버튼 추가
|
||||
self.buttons_layout.addWidget(self.remove_db_checkbox)
|
||||
self.buttons_layout.addWidget(self.view_data_button)
|
||||
self.buttons_layout.addWidget(self.run_button)
|
||||
|
|
@ -475,11 +483,21 @@ class MainWindow(QMainWindow):
|
|||
self.log(f"크롬 프로파일 경로가 설정되었습니다: {self.chrome_bookmarks_path}")
|
||||
self.log(f"웨일 프로파일 경로가 설정되었습니다: {self.whale_bookmarks_path}")
|
||||
|
||||
# 아이콘 설정 (추가된 부분)
|
||||
self.set_app_icon()
|
||||
|
||||
def update_chunk_size(self):
|
||||
"""폴더당 북마크 갯수 변경 시 chunk_size 업데이트"""
|
||||
# self.log(f"폴더당 북마크 갯수가 변경되었습니다: {self.worker.chunk_size}")
|
||||
|
||||
def set_app_icon(self):
|
||||
"""애플리케이션 아이콘을 설정합니다."""
|
||||
base_dir = self.get_base_dir()
|
||||
icon_path = os.path.join(base_dir, "bookmaker.ico")
|
||||
if os.path.exists(icon_path):
|
||||
self.setWindowIcon(QIcon(icon_path))
|
||||
else:
|
||||
pass
|
||||
|
||||
# 브라우저 실행 파일 경로 가져오기
|
||||
def get_browser_path(self, browser_name):
|
||||
|
|
@ -623,6 +641,38 @@ class MainWindow(QMainWindow):
|
|||
self.log("DB 파일이 로드되었습니다.")
|
||||
self.view_data_button.setEnabled(True)
|
||||
|
||||
def get_base_dir(self):
|
||||
"""
|
||||
실행 환경에 따라 base_dir을 설정하는 메서드.
|
||||
cx_Freeze로 패키징된 경우 실행 파일의 경로, 일반 Python 환경일 경우 __file__을 기준으로 설정.
|
||||
"""
|
||||
if getattr(sys, 'frozen', False): # 패키징된 경우
|
||||
base_dir = os.path.dirname(sys.executable)
|
||||
internal_dir = os.path.join(base_dir, 'lib', 'src') # lib 디렉토리 포함
|
||||
if os.path.exists(internal_dir): # lib 디렉토리가 존재하면 base_dir로 설정
|
||||
return internal_dir
|
||||
|
||||
else: # 일반 Python 실행 환경
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
debug_dir = os.path.join(base_dir, 'src') # lib 디렉토리 포함
|
||||
|
||||
return debug_dir
|
||||
|
||||
def load_sample_excel(self):
|
||||
"""'추가양식.xlsx' 파일을 엽니다."""
|
||||
try:
|
||||
base_dir = self.get_base_dir()
|
||||
file_path = os.path.join(base_dir, "추가양식.xlsx")
|
||||
if os.path.exists(file_path):
|
||||
os.startfile(file_path)
|
||||
self.log(f"추가 양식 파일 열기: {file_path}")
|
||||
else:
|
||||
self.log(f"추가 양식 파일을 찾을 수 없습니다: {file_path}")
|
||||
QMessageBox.warning(self, "파일 없음", "추가 양식 파일을 찾을 수 없습니다.")
|
||||
except Exception as e:
|
||||
self.log(f"추가 양식 파일 열기 중 오류 발생: {str(e)}", exc_info=True)
|
||||
QMessageBox.critical(self, "오류", f"추가 양식 파일을 열 수 없습니다: {str(e)}")
|
||||
|
||||
def load_excel(self):
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "엑셀 파일 선택", "", "Excel Files (*.xlsx *.xls)")
|
||||
if not file_path:
|
||||
|
|
@ -634,8 +684,16 @@ class MainWindow(QMainWindow):
|
|||
# 파일 확장자 확인
|
||||
ext = os.path.splitext(file_path)[-1].lower()
|
||||
|
||||
# 필수 열 이름 정의
|
||||
required_columns = ['country', 'mall_grade', 'mall_name', 'mall_url']
|
||||
# 열 이름 매핑 정의
|
||||
column_name_mapping = {
|
||||
'mall_url': ['mall_url(필수)', 'mall_url', '마켓링크', 'URL'],
|
||||
'mall_name': ['mall_name', '셀러명', '판매자명'],
|
||||
'mall_grade': ['mall_grade', '등급', '판매자등급'],
|
||||
'country': ['country', '국가', '지역']
|
||||
}
|
||||
|
||||
required_columns = ['mall_url']
|
||||
all_expected_columns = list(column_name_mapping.keys())
|
||||
|
||||
# 엑셀 파일 읽기
|
||||
if ext == ".xls":
|
||||
|
|
@ -658,22 +716,34 @@ class MainWindow(QMainWindow):
|
|||
self.log("지원되지 않는 파일 형식입니다. .xls 또는 .xlsx 파일을 선택하세요.")
|
||||
return
|
||||
|
||||
# 엑셀에서 가져온 열과 필수 열 비교
|
||||
available_columns = [col for col in required_columns if col in df.columns]
|
||||
if not available_columns:
|
||||
self.log("엑셀 파일에 필수 열이 없습니다. 필요한 열: " + ", ".join(required_columns))
|
||||
# 엑셀 열 이름과 정의된 이름 매핑
|
||||
rename_dict = {}
|
||||
excel_columns = df.columns.tolist()
|
||||
for internal_name, possible_names in column_name_mapping.items():
|
||||
for excel_col in excel_columns:
|
||||
if excel_col in possible_names:
|
||||
rename_dict[excel_col] = internal_name
|
||||
break # 하나라도 매칭되면 다음 내부 이름으로 이동
|
||||
|
||||
# 데이터프레임 열 이름 변경
|
||||
df.rename(columns=rename_dict, inplace=True)
|
||||
|
||||
# 필수 열이 있는지 확인
|
||||
if 'mall_url' not in df.columns:
|
||||
self.log(f"엑셀 파일에 필수 열({column_name_mapping['mall_url']}) 중 하나라도 있어야 합니다.")
|
||||
return
|
||||
|
||||
# 필요한 열만 가져오기
|
||||
df = df[available_columns]
|
||||
# 필요한 열만 선택 (매핑된 내부 이름 사용)
|
||||
available_columns = [col for col in all_expected_columns if col in df.columns]
|
||||
df = df[available_columns].copy()
|
||||
|
||||
# 누락된 열은 빈 값으로 추가
|
||||
for col in required_columns:
|
||||
# 누락된 열은 빈 값으로 채우기
|
||||
for col in all_expected_columns:
|
||||
if col not in df.columns:
|
||||
df[col] = "" # 누락된 열은 빈 값으로 채움
|
||||
df[col] = ""
|
||||
|
||||
# 열 이름을 정렬하여 설정
|
||||
df = df[required_columns]
|
||||
# 열 순서 설정 (데이터베이스 테이블 순서와 맞춤)
|
||||
df = df[['country', 'mall_grade', 'mall_name', 'mall_url']]
|
||||
|
||||
# datetime.time 타입 데이터를 문자열로 변환
|
||||
def convert_time_to_string(x):
|
||||
|
|
@ -691,6 +761,7 @@ class MainWindow(QMainWindow):
|
|||
df['mall_url'] = df['mall_url'].apply(convert_time_to_string)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
if self.remove_db_checkbox.isChecked():
|
||||
# 기존 DB 제거 및 새 테이블 생성
|
||||
|
|
@ -714,22 +785,42 @@ class MainWindow(QMainWindow):
|
|||
# 컬럼이 이미 있는 경우 무시
|
||||
pass
|
||||
|
||||
# 데이터 저장, 중복 방지
|
||||
df.drop_duplicates(subset=['mall_url'], inplace=True)
|
||||
added_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
# id 열을 자동 생성하지 않으므로, 기존 테이블 스키마를 유지하면서 데이터를 삽입
|
||||
# 데이터 저장 및 중복 방지
|
||||
for _, row in df.iterrows():
|
||||
conn.execute("""
|
||||
INSERT INTO markets (country, mall_grade, mall_name, mall_url)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (row['country'], row['mall_grade'], row['mall_name'], row['mall_url']))
|
||||
mall_url = row['mall_url']
|
||||
cursor.execute("SELECT mall_url FROM markets WHERE mall_url=?", (mall_url,))
|
||||
existing_mall = cursor.fetchone()
|
||||
if not existing_mall:
|
||||
cursor.execute("""
|
||||
INSERT INTO markets (country, mall_grade, mall_name, mall_url)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (row['country'], row['mall_grade'], row['mall_name'], mall_url))
|
||||
self.log(f"새로운 몰 추가: {mall_url}")
|
||||
added_count += 1
|
||||
else:
|
||||
self.log(f"중복된 몰 건너뛰기: {mall_url}")
|
||||
skipped_count += 1
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
self.log("DB 저장 완료")
|
||||
|
||||
self.show_load_excel_result_message(added_count, skipped_count)
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"엑셀 파일을 불러오는 중 에러 발생: {str(e)}", exc_info=True)
|
||||
|
||||
def show_load_excel_result_message(self, added_count, skipped_count):
|
||||
"""엑셀 로드 완료 후 결과를 메시지 박스로 보여줍니다."""
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"엑셀 처리 완료",
|
||||
f"총 {added_count}개의 몰이 추가되었고, {skipped_count}개의 중복된 몰은 제외되었습니다."
|
||||
)
|
||||
|
||||
def view_data(self):
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
|
|
|
|||
BIN
markets.db
BIN
markets.db
Binary file not shown.
Binary file not shown.
6
setup.py
6
setup.py
|
|
@ -17,12 +17,14 @@ main_file = "main.py"
|
|||
|
||||
# 필요한 추가 파일 설정 (예: 리소스 파일, 아이콘 등)
|
||||
include_files = [
|
||||
("markets.db", "markets.db"), # 데이터베이스 파일 (필요 시)
|
||||
("markets.db", "markets.db"),
|
||||
("추가양식.xlsx", "lib/src/추가양식.xlsx"),
|
||||
("bookmaker.ico", "lib/src/bookmaker.ico"), # 아이콘 파일 포함 확인
|
||||
]
|
||||
|
||||
# 빌드 옵션
|
||||
build_options = {
|
||||
"packages": ["os", "sys", "sqlite3", "subprocess", "psutil", "pygetwindow", "glob","json", "pandas", "datetime", "PySide6", "openpyxl"],
|
||||
"packages": ["os", "sys", "sqlite3", "subprocess", "psutil", "pygetwindow", "glob","json", "pandas", "datetime", "PySide6", "openpyxl", "xlrd"],
|
||||
"include_files": include_files,
|
||||
"excludes": ['PySide6.QtAsyncio.events'], # tkinter 미사용 시 제외
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
__version__ = "1.3.3"
|
||||
__version__ = "1.3.4"
|
||||
|
|
|
|||
Loading…
Reference in New Issue