Merge branch 'master' of ssh://cckb9998.synology.me:30022/ckh08045/baidu_web

This commit is contained in:
9700X_PC 2024-11-12 13:13:34 +09:00
commit 48f5d4ff54
16 changed files with 614 additions and 16 deletions

20
gui2.py
View File

@ -113,23 +113,26 @@ class ProductViewer(QWidget):
self.price_label.setText(f"가격: {product[4]}")
self.page_button.setText(f"{self.product_index + 1}/{self.total_products}")
# self.reset_card_widgets() # 상품 카드 리셋
# 이미지 로드
self.load_image_from_url(self.image_label, product[2])
self.reset_card_widgets() # 상품 카드 리셋
# 중간 레이아웃에 있는 카드 레이아웃 초기화 및 데이터 로드
search_results = self.load_search_results(product[0])
for i, card in enumerate(self.card_layouts):
if i < len(search_results):
result = search_results[i]
print(f"f{result}")
card["name"].setText(result[0][:30] + "..." if len(result[0]) > 30 else result[2]) # 상품명 길이 제한
print(f"card[name], result[0] : {result[0]}")
card["price"].setText(result[2])
print(f"card[price], result[2] : {result[2]}")
card["select"].setText("미선택")
card["widget"].setStyleSheet("border: 2px solid black;")
# 각 카드에 이미지 로드
self.load_image_from_url(card["image"], result[3]) # 이미지 URL에 맞춰 수정
print(f"card[image], result[3] : {result[3]}")
else:
card["name"].setText("")
@ -150,6 +153,7 @@ class ProductViewer(QWidget):
def load_image_from_url(self, label, url):
try:
response = requests.get(url)
print(f"load_image_from_url : {url}")
if response.status_code == 200:
pixmap = QPixmap()
pixmap.loadFromData(BytesIO(response.content).read())
@ -206,7 +210,15 @@ class ProductViewer(QWidget):
elif event.key() in [Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5]:
index = event.key() - Qt.Key_1
if index < len(self.card_layouts) and self.card_layouts[index]["name"].text():
self.select_card(index)
# 현재 product_id와 search_result_id를 함께 전달
product_id = self.products[self.product_index][0] # 현재 product_id 가져오기
search_results = self.load_search_results(product_id)
if index < len(search_results):
search_result_id = search_results[index][0] # search_result_id 가져오기
self.select_card(product_id, search_result_id)
else:
QMessageBox.warning(self, "경고", "올바른 키를 입력하세요.", QMessageBox.Ok)
elif event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
self.show_product_dialog()
else:

163
gui33.py Normal file
View File

@ -0,0 +1,163 @@
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QDialog
from PySide6.QtCore import Qt
import sqlite3
import sys
from productCard import ProductCard # ProductCard 클래스 임포트
from searchResultCard import SearchResultCard # SearchResultCard 클래스 임포트
class ProductViewer(QWidget):
def __init__(self, db_path):
super().__init__()
self.conn = sqlite3.connect(db_path)
self.product_index = 0
self.products = self.load_products()
self.total_products = len(self.products)
# UI 초기화
self.init_ui()
self.load_product_data()
def init_ui(self):
self.setWindowTitle("Product Viewer")
main_layout = QVBoxLayout()
# 상단 레이아웃에 ProductCard를 추가
self.product_card = ProductCard()
main_layout.addWidget(self.product_card)
# 중간 레이아웃에 여러 개의 SearchResultCard를 추가
self.middle_layout = QHBoxLayout()
self.search_result_cards = [SearchResultCard(i+1) for i in range(5)]
for card in self.search_result_cards:
self.middle_layout.addWidget(card)
main_layout.addLayout(self.middle_layout)
# 하단 레이아웃
self.bottom_layout = QHBoxLayout()
self.left_button = QPushButton("")
self.left_button.clicked.connect(self.previous_product)
self.page_button = QPushButton(f"{self.product_index + 1}/{self.total_products}")
self.page_button.clicked.connect(self.show_product_dialog)
self.right_button = QPushButton("")
self.right_button.clicked.connect(self.next_product)
self.bottom_layout.addWidget(self.left_button)
self.bottom_layout.addWidget(self.page_button)
self.bottom_layout.addWidget(self.right_button)
main_layout.addLayout(self.bottom_layout)
self.setLayout(main_layout)
def load_products(self):
# DB에서 products 테이블 데이터를 로드
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM products")
products = cursor.fetchall()
return products
def load_product_data(self):
# 현재 상품 데이터를 로드하여 ProductCard에 설정
product = self.products[self.product_index]
product_name = product[1]
product_price = product[4]
product_img_url = product[2]
self.product_card.set_data(name=product_name, price=product_price, img_url=product_img_url)
print(f"product : {product}")
print(f"product_name : {product_name}")
print(f"product_price : {product_price}")
print(f"product_img_url : {product_img_url}")
# SearchResultCard 초기화 및 데이터 로드
self.reset_search_result_cards() # 이전 카드 데이터 리셋
search_results = self.load_search_results(product[0])
print(f"search_results : {search_results}")
for i, result in enumerate(search_results):
if i < len(self.search_result_cards):
title = result[1]
print(f"{i}번째 title : {title}")
price = result[3]
print(f"{i}번째 price : {price}")
source = result[2]
print(f"{i}번째 source : {source}")
img_url = result[4]
print(f"{i}번째 img_url : {img_url}")
self.search_result_cards[i].set_data(name=title, price=price, source=source, img_url=img_url)
# 페이지 버튼 텍스트 업데이트
self.page_button.setText(f"{self.product_index + 1}/{self.total_products}")
def reset_search_result_cards(self):
# 각 SearchResultCard를 초기화
for card in self.search_result_cards:
card.reset()
def load_search_results(self, product_id):
# DB에서 search_results 테이블의 데이터를 로드
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM search_results WHERE product_id=?", (product_id,))
return cursor.fetchall()
def previous_product(self):
if self.product_index > 0:
self.product_index -= 1
self.load_product_data()
def next_product(self):
if self.product_index < self.total_products - 1:
self.product_index += 1
self.load_product_data()
def show_product_dialog(self):
# 현재 상품 정보를 다이얼로그로 보여줌
dialog = ProductDialog(self)
dialog.exec()
def keyPressEvent(self, event):
# 키보드 이벤트 처리
if event.key() == Qt.Key_Left:
self.previous_product()
elif event.key() == Qt.Key_Right:
self.next_product()
elif event.key() == Qt.Key_Escape:
self.close()
elif event.key() in [Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5]:
index = event.key() - Qt.Key_1
if index < len(self.search_result_cards) and self.search_result_cards[index].name_value.text():
self.select_card(index)
elif event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
self.show_product_dialog()
def select_card(self, index):
# 선택된 카드의 UI 갱신 및 데이터베이스 업데이트
for i, card in enumerate(self.search_result_cards):
if i == index:
card.set_selected(True)
else:
card.set_selected(False)
class ProductDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("상품 리스트")
layout = QVBoxLayout(self)
cursor = parent.conn.cursor()
cursor.execute("SELECT * FROM products")
products = cursor.fetchall()
for product in products:
label = QLabel(f"{product[1]} - {product[3]}")
layout.addWidget(label)
self.setLayout(layout)
def keyPressEvent(self, event):
if event.key() in {Qt.Key_Escape, Qt.Key_Return, Qt.Key_Enter}:
self.accept() # 다이얼로그 닫기
if __name__ == "__main__":
app = QApplication(sys.argv)
viewer = ProductViewer("products.db")
viewer.show()
sys.exit(app.exec())

View File

@ -51,21 +51,29 @@ class BaiduImageSearcher:
if self.playwright:
self.playwright.stop()
def upload_image(self, image_path):
def check_capcha(self):
try:
# 현재 URL 확인 및 로그 출력
# current_url = self.page.url
current_url = self.page.evaluate("() => window.location.href")
self.logger.warning(f"Timeout occurred. Current URL: {current_url}")
self.logger.info(f"Current URL: {current_url}")
# 에러 페이지 조건 확인
if current_url.startswith('https://graph.baidu.com/errpage'):
self.logger.warning("Error page detected. Navigating back.")
self.page.go_back() # 뒤로 가기
# self.page.go_back() # 뒤로 가기
# self.page.goto(self.initial_url) # 최초 접속 URL
return True
else:
return False
except Exception as e:
self.logger.error(f"Finding Error page occured ERROR: {e}", exc_info=True)
return False
def upload_image(self, image_path):
try:
if self.check_capcha():
return False
# 첫 번째 검색과 이후 검색의 선택자를 다르게 설정
# if self.is_first_search:
@ -83,27 +91,45 @@ class BaiduImageSearcher:
self.page.wait_for_selector(upload_button_xpath)
self.page.click(upload_button_xpath)
if self.check_capcha():
return False
self.page.wait_for_selector(upload_input_xpath)
self.page.set_input_files(upload_input_xpath, image_path)
return True
except Exception as e:
self.logger.error(f"Error in upload_image: {e}", exc_info=True)
def expand_results(self):
# 확장 버튼 클릭 및 확장된 상품 카드 요소 로드 대기
if self.check_capcha():
return False
self.logger.info("expand_results")
expand_button_xpath = '//*[@id="app"]/div/div[2]/div/div[1]/ul/li[2]'
self.page.wait_for_selector(expand_button_xpath)
self.page.click(expand_button_xpath)
if self.check_capcha():
return False
# 확장된 상품 카드 이미지 요소가 로드될 때까지 대기
self.logger.info("확장된 상품 카드 이미지 요소가 로드될 때까지 대기")
product_card_selector = 'div.graph-product-list-img img'
self.page.wait_for_selector(product_card_selector)
if self.check_capcha():
return False
return True
def extract_product_data(self):
# 검색 결과 페이지에서 JSON 데이터 추출
if self.check_capcha():
return False
content = None
self.logger.info("검색 결과 페이지에서 JSON 데이터 추출")
content = self.page.content()
soup = BeautifulSoup(content, 'html.parser')
script_tag = soup.select_one("html > head > script:nth-of-type(2)")
@ -113,7 +139,7 @@ class BaiduImageSearcher:
match = re.search(r"window\.cardData\s*=\s*(\[\{.*\}\]);", raw_data, re.DOTALL)
if match:
json_data_str = match.group(1)
print(f"[json_data_str]\n{json_data_str}")
try:
data = json.loads(json_data_str)
product_info = []
@ -142,6 +168,8 @@ class BaiduImageSearcher:
})
self.logger.info("product_info 추출 완료")
self.logger.info(f"{product_info}")
input("로그를 확인한 후 아무 키나 눌러서 계속하세요...")
return product_info
except json.JSONDecodeError as e:
print("JSON 디코딩 오류:", e)

View File

@ -20,6 +20,30 @@ class MainProcessor:
self.image_searcher.start_browser()
# # 각 상품에 대해 이미지 검색 수행
# for product, product_id in zip(products, product_ids):
# try:
# if product_id is None:
# self.logger.error("Failed to insert product into database.")
# continue
# # 이미지 다운로드 및 검색 실행
# image_path = self.image_downloader.download_image(product['image_url'], product_id)
# is_success_upload_image = self.image_searcher.upload_image(image_path)
# is_success_expand_results = self.image_searcher.expand_results()
# # 검색 결과를 추출하여 DB에 저장
# search_results = self.image_searcher.extract_product_data()
# self.db_manager.insert_search_results(product_id, search_results)
# os.remove(image_path)
# self.logger.debug(f"Processed product ID: {product_id}")
# time.sleep(1)
# except Exception as e:
# self.logger.warning(f"Failed to process product ID: {product_id} - {e}", exc_info=True)
# 각 상품에 대해 이미지 검색 수행
for product, product_id in zip(products, product_ids):
try:
@ -29,20 +53,57 @@ class MainProcessor:
# 이미지 다운로드 및 검색 실행
image_path = self.image_downloader.download_image(product['image_url'], product_id)
self.image_searcher.upload_image(image_path)
self.image_searcher.expand_results()
# 검색 결과를 추출하여 DB에 저장
search_results = self.image_searcher.extract_product_data()
# 재시도 횟수 설정
max_retries = 3
attempt = 0
is_success_upload_image = False
is_success_expand_results = False
search_results = None
while attempt < max_retries:
# upload_image 메서드 실행 및 성공 여부 확인
is_success_upload_image = self.image_searcher.upload_image(image_path)
if not is_success_upload_image:
attempt += 1
self.logger.warning(f"Upload image failed for Product ID [{product_id}]. Retry {attempt}/{max_retries}")
time.sleep(1)
continue # 재시도 시 루프를 다시 시작
# expand_results 메서드 실행 및 성공 여부 확인
is_success_expand_results = self.image_searcher.expand_results()
if not is_success_expand_results:
attempt += 1
self.logger.warning(f"Expand results failed for Product ID [{product_id}]. Retry {attempt}/{max_retries}")
time.sleep(1)
continue # 재시도 시 루프를 다시 시작
# 검색 결과 추출
search_results = self.image_searcher.extract_product_data()
if not search_results:
attempt += 1
self.logger.warning(f"Extract product data failed for Product ID [{product_id}]. Retry {attempt}/{max_retries}")
time.sleep(1)
continue # 재시도 시 루프를 다시 시작
# 모든 작업이 성공하면 루프 종료
if is_success_upload_image and is_success_expand_results and search_results:
break
else:
# 재시도 횟수 초과 시 경고 로그 출력 및 다음 제품으로 이동
self.logger.error(f"Failed to process Product ID [{product_id}] after {max_retries} attempts.")
continue
# 성공 시 검색 결과를 DB에 저장
self.db_manager.insert_search_results(product_id, search_results)
os.remove(image_path)
self.logger.debug(f"Processed product ID: {product_id}")
time.sleep(1)
except Exception as e:
self.logger.warning(f"Failed to process product ID: {product_id} - {e}", exc_info=True)
def show_results(self):
# 검색 결과 출력
try:

167
productCard.py Normal file
View File

@ -0,0 +1,167 @@
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel
from PySide6.QtGui import QPixmap
from PySide6.QtCore import Qt
import requests
class ProductCard(QWidget):
def __init__(self, index=1):
super().__init__()
self.setFixedSize(220, 300)
self.layout = QGridLayout(self)
# UI 요소 초기화
self.index_label = QLabel(str(index))
self.index_label.setAlignment(Qt.AlignCenter)
self.index_label.setStyleSheet("font-weight: bold; font-size: 16px;")
self.image_label = QLabel()
self.image_label.setFixedSize(200, 140)
self.name_label = QLabel("상품명:")
self.name_value = QLabel("")
self.name_value.setWordWrap(True)
self.name_value.setFixedSize(120, 50)
self.price_label = QLabel("가격:")
self.price_value = QLabel("")
self.select_label = QLabel("미선택")
self.select_label.setAlignment(Qt.AlignCenter)
self.select_label.setStyleSheet("font-weight: bold; color: black;")
# 레이아웃 구성
self.layout.addWidget(self.index_label, 0, 0, 1, 2)
self.layout.addWidget(self.image_label, 1, 0, 1, 2)
self.layout.addWidget(self.name_label, 2, 0)
self.layout.addWidget(self.name_value, 2, 1)
self.layout.addWidget(self.price_label, 3, 0)
self.layout.addWidget(self.price_value, 3, 1)
self.layout.addWidget(self.select_label, 4, 0, 1, 2)
def reset(self):
"""카드의 데이터를 초기화합니다."""
self.name_value.setText("")
self.price_value.setText("")
self.image_label.clear()
self.set_selected(False)
def set_data(self, name, price, img_url):
"""카드에 상품 데이터를 설정합니다."""
self.name_value.setText(name)
self.price_value.setText(str(price))
# 이미지 설정
pixmap = QPixmap()
img_data = self.download_image_data(img_url)
if img_data:
pixmap.loadFromData(img_data)
self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio))
else:
self.image_label.clear()
def download_image_data(self, img_url):
"""이미지 URL에서 데이터를 다운로드합니다."""
try:
response = requests.get(img_url)
if response.status_code == 200:
return response.content
except Exception as e:
print(f"Image download error: {e}")
return None
def set_selected(self, selected):
"""카드의 선택 상태를 설정합니다."""
if selected:
self.select_label.setText("선택")
self.select_label.setStyleSheet("font-weight: bold; color: red;")
self.setStyleSheet("border: 2px solid red;")
else:
self.select_label.setText("미선택")
self.select_label.setStyleSheet("font-weight: bold; color: black;")
self.setStyleSheet("border: 1px solid grey;")
class SearchResultCard(QWidget):
def __init__(self, index=1):
super().__init__()
self.setFixedSize(220, 300)
self.layout = QGridLayout(self)
# UI 요소 초기화
self.index_label = QLabel(str(index))
self.index_label.setAlignment(Qt.AlignCenter)
self.index_label.setStyleSheet("font-weight: bold; font-size: 16px;")
self.image_label = QLabel()
self.image_label.setFixedSize(200, 140)
self.name_label = QLabel("상품명:")
self.name_value = QLabel("")
self.name_value.setWordWrap(True)
self.name_value.setFixedSize(120, 50)
self.price_label = QLabel("가격:")
self.price_value = QLabel("")
self.source_label = QLabel("출처:")
self.source_value = QLabel("")
self.select_label = QLabel("미선택")
self.select_label.setAlignment(Qt.AlignCenter)
self.select_label.setStyleSheet("font-weight: bold; color: black;")
# 레이아웃 구성
self.layout.addWidget(self.index_label, 0, 0, 1, 2)
self.layout.addWidget(self.image_label, 1, 0, 1, 2)
self.layout.addWidget(self.name_label, 2, 0)
self.layout.addWidget(self.name_value, 2, 1)
self.layout.addWidget(self.price_label, 3, 0)
self.layout.addWidget(self.price_value, 3, 1)
self.layout.addWidget(self.source_label, 4, 0)
self.layout.addWidget(self.source_value, 4, 1)
self.layout.addWidget(self.select_label, 5, 0, 1, 2)
def reset(self):
"""카드의 데이터를 초기화합니다."""
self.name_value.setText("")
self.price_value.setText("")
self.source_value.setText("")
self.image_label.clear()
self.set_selected(False)
def set_data(self, name, price, source, img_url):
"""카드에 검색 결과 데이터를 설정합니다."""
self.name_value.setText(name)
self.price_value.setText(price)
self.source_value.setText(source)
# 이미지 설정
pixmap = QPixmap()
img_data = self.download_image_data(img_url)
if img_data:
pixmap.loadFromData(img_data)
self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio))
else:
self.image_label.clear()
def download_image_data(self, img_url):
"""이미지 URL에서 데이터를 다운로드합니다."""
try:
response = requests.get(img_url)
if response.status_code == 200:
return response.content
except Exception as e:
print(f"Image download error: {e}")
return None
def set_selected(self, selected):
"""카드의 선택 상태를 설정합니다."""
if selected:
self.select_label.setText("선택")
self.select_label.setStyleSheet("font-weight: bold; color: red;")
self.setStyleSheet("border: 2px solid red;")
else:
self.select_label.setText("미선택")
self.select_label.setStyleSheet("font-weight: bold; color: black;")
self.setStyleSheet("border: 1px solid grey;")

Binary file not shown.

BIN
requirements.txt Normal file

Binary file not shown.

167
searchResultCard.py Normal file
View File

@ -0,0 +1,167 @@
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel
from PySide6.QtGui import QPixmap
from PySide6.QtCore import Qt
import requests
class ProductCard(QWidget):
def __init__(self, index=1):
super().__init__()
self.setFixedSize(220, 300)
self.layout = QGridLayout(self)
# UI 요소 초기화
self.index_label = QLabel(str(index))
self.index_label.setAlignment(Qt.AlignCenter)
self.index_label.setStyleSheet("font-weight: bold; font-size: 16px;")
self.image_label = QLabel()
self.image_label.setFixedSize(200, 140)
self.name_label = QLabel("상품명:")
self.name_value = QLabel("")
self.name_value.setWordWrap(True)
self.name_value.setFixedSize(120, 50)
self.price_label = QLabel("가격:")
self.price_value = QLabel("")
self.select_label = QLabel("미선택")
self.select_label.setAlignment(Qt.AlignCenter)
self.select_label.setStyleSheet("font-weight: bold; color: black;")
# 레이아웃 구성
self.layout.addWidget(self.index_label, 0, 0, 1, 2)
self.layout.addWidget(self.image_label, 1, 0, 1, 2)
self.layout.addWidget(self.name_label, 2, 0)
self.layout.addWidget(self.name_value, 2, 1)
self.layout.addWidget(self.price_label, 3, 0)
self.layout.addWidget(self.price_value, 3, 1)
self.layout.addWidget(self.select_label, 4, 0, 1, 2)
def reset(self):
"""카드의 데이터를 초기화합니다."""
self.name_value.setText("")
self.price_value.setText("")
self.image_label.clear()
self.set_selected(False)
def set_data(self, name, price, img_url):
"""카드에 상품 데이터를 설정합니다."""
self.name_value.setText(name)
self.price_value.setText(price)
# 이미지 설정
pixmap = QPixmap()
img_data = self.download_image_data(img_url)
if img_data:
pixmap.loadFromData(img_data)
self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio))
else:
self.image_label.clear()
def download_image_data(self, img_url):
"""이미지 URL에서 데이터를 다운로드합니다."""
try:
response = requests.get(img_url)
if response.status_code == 200:
return response.content
except Exception as e:
print(f"Image download error: {e}")
return None
def set_selected(self, selected):
"""카드의 선택 상태를 설정합니다."""
if selected:
self.select_label.setText("선택")
self.select_label.setStyleSheet("font-weight: bold; color: red;")
self.setStyleSheet("border: 2px solid red;")
else:
self.select_label.setText("미선택")
self.select_label.setStyleSheet("font-weight: bold; color: black;")
self.setStyleSheet("border: 1px solid grey;")
class SearchResultCard(QWidget):
def __init__(self, index=1):
super().__init__()
self.setFixedSize(220, 300)
self.layout = QGridLayout(self)
# UI 요소 초기화
self.index_label = QLabel(str(index))
self.index_label.setAlignment(Qt.AlignCenter)
self.index_label.setStyleSheet("font-weight: bold; font-size: 16px;")
self.image_label = QLabel()
self.image_label.setFixedSize(200, 140)
self.name_label = QLabel("상품명:")
self.name_value = QLabel("")
self.name_value.setWordWrap(True)
self.name_value.setFixedSize(120, 50)
self.price_label = QLabel("가격:")
self.price_value = QLabel("")
self.source_label = QLabel("출처:")
self.source_value = QLabel("")
self.select_label = QLabel("미선택")
self.select_label.setAlignment(Qt.AlignCenter)
self.select_label.setStyleSheet("font-weight: bold; color: black;")
# 레이아웃 구성
self.layout.addWidget(self.index_label, 0, 0, 1, 2)
self.layout.addWidget(self.image_label, 1, 0, 1, 2)
self.layout.addWidget(self.name_label, 2, 0)
self.layout.addWidget(self.name_value, 2, 1)
self.layout.addWidget(self.price_label, 3, 0)
self.layout.addWidget(self.price_value, 3, 1)
self.layout.addWidget(self.source_label, 4, 0)
self.layout.addWidget(self.source_value, 4, 1)
self.layout.addWidget(self.select_label, 5, 0, 1, 2)
def reset(self):
"""카드의 데이터를 초기화합니다."""
self.name_value.setText("")
self.price_value.setText("")
self.source_value.setText("")
self.image_label.clear()
self.set_selected(False)
def set_data(self, name, price, source, img_url):
"""카드에 검색 결과 데이터를 설정합니다."""
self.name_value.setText(name)
self.price_value.setText(price)
self.source_value.setText(source)
# 이미지 설정
pixmap = QPixmap()
img_data = self.download_image_data(img_url)
if img_data:
pixmap.loadFromData(img_data)
self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio))
else:
self.image_label.clear()
def download_image_data(self, img_url):
"""이미지 URL에서 데이터를 다운로드합니다."""
try:
response = requests.get(img_url)
if response.status_code == 200:
return response.content
except Exception as e:
print(f"Image download error: {e}")
return None
def set_selected(self, selected):
"""카드의 선택 상태를 설정합니다."""
if selected:
self.select_label.setText("선택")
self.select_label.setStyleSheet("font-weight: bold; color: red;")
self.setStyleSheet("border: 2px solid red;")
else:
self.select_label.setText("미선택")
self.select_label.setStyleSheet("font-weight: bold; color: black;")
self.setStyleSheet("border: 1px solid grey;")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 116 KiB

BIN
temp/22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
temp/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.