Python 을 이용하여 UNSLPLASH 의 이미지를 검색하여 다운받을 수 있는 프로그램.

python

 

Python 을 이용하여 UNSLPLASH 의 이미지를 검색하여 다운받을 수 있는 프로그램.

  • 제약: 1시간에 최대 5번 (1회 최대 300장검색)
  • API KEY : unsplash 에서 발급받아 아래 API_KEY 에 넣어서 사용가능.
  • 아래 코드는 MAC 환경에서 제작되었으며, WINDOWS에서는 경로등을 수정해야함.



import sys
import requests
import os
import time
from urllib.parse import quote
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QPushButton, QLabel, QGridLayout, QMessageBox, QScrollArea,
QDialog, QComboBox, QDialogButtonBox, QCheckBox)
from PyQt6.QtGui import QPixmap, QImage, QPainter, QPen
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QRect, QPoint

# Unsplash API 설정
API_KEY = "Your_API_KEY" # 여기에 발급받은 Access Key를 입력하세요
BASE_URL = "https://api.unsplash.com/search/photos"

class ImageFetcher(QThread):
imagesFetched = pyqtSignal(list)

def __init__(self, keyword, max_pages=10, per_page=30):
super().__init__()
self.keyword = keyword
self.max_pages = max_pages
self.per_page = per_page

def run(self):
encoded_keyword = quote(self.keyword.encode('utf-8'))
all_images = []
for page in range(1, self.max_pages + 1):
params = {
"query": encoded_keyword,
"page": page,
"per_page": self.per_page,
"client_id": API_KEY
}
try:
response = requests.get(BASE_URL, params=params)
response.raise_for_status()
data = response.json()
images = [(img["urls"]["regular"], img["urls"]["small"], img["urls"]["regular"], img["urls"]["full"])
for img in data.get("results", [])]
all_images.extend(images)
print(f"페이지 {page} 로드 완료: {len(images)}개 이미지")
if not images:
break
except requests.exceptions.RequestException as e:
print(f"페이지 {page} 오류: {e}")
break
self.imagesFetched.emit(all_images)

class ImageLabel(QLabel):
def __init__(self, regular_url, small_url, full_url, main_window):
super().__init__()
self.regular_url = regular_url
self.small_url = small_url
self.full_url = full_url
self.main_window = main_window
self.selected = False
self.setScaledContents(True)
self.load_image()

def load_image(self):
try:
response = requests.get(self.regular_url)
image = QImage.fromData(response.content)
pixmap = QPixmap.fromImage(image).scaled(200, 200, Qt.AspectRatioMode.KeepAspectRatio)
self.setPixmap(pixmap)
except Exception as e:
self.setText(f"로드 실패: {e}")

def set_selected(self, selected):
self.selected = selected
self.setStyleSheet("border: 3px solid red;" if selected else "")
if selected:
self.main_window.select_image(self)
else:
self.main_window.deselect_image(self)

def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.set_selected(not self.selected)

class DragSelectionWidget(QWidget):
def __init__(self, main_window):
super().__init__()
self.main_window = main_window
self.start_pos = None
self.end_pos = None
self.dragging = False

def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.start_pos = event.pos()
self.dragging = True

def mouseMoveEvent(self, event):
if self.dragging:
self.end_pos = event.pos()
self.update()

def mouseReleaseEvent(self, event):
if self.dragging:
self.end_pos = event.pos()
self.dragging = False
self.select_images_in_rect()
self.update()

def paintEvent(self, event):
if self.dragging and self.start_pos and self.end_pos:
painter = QPainter(self)
pen = QPen(Qt.GlobalColor.blue, 2, Qt.PenStyle.DashLine)
painter.setPen(pen)
rect = QRect(self.start_pos, self.end_pos).normalized()
painter.drawRect(rect)

def select_images_in_rect(self):
if not self.start_pos or not self.end_pos:
return
rect = QRect(self.start_pos, self.end_pos).normalized()
scroll_widget = self.main_window.scroll_widget
for image_label in self.main_window.image_labels:
label_pos = scroll_widget.mapTo(self, image_label.pos())
label_rect = QRect(label_pos, image_label.size())
if rect.intersects(label_rect):
image_label.set_selected(not image_label.selected)

class DownloadDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("다운로드 옵션")

layout = QVBoxLayout(self)
self.quality_label = QLabel("다운로드 품질 선택:")
self.quality_combo = QComboBox()
self.quality_combo.addItems(["Small (저화질)", "Regular (중간)", "Full (고화질)"])
self.quality_combo.setCurrentIndex(2)
layout.addWidget(self.quality_label)
layout.addWidget(self.quality_combo)

self.buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
layout.addWidget(self.buttons)

def get_selected_quality(self):
index = self.quality_combo.currentIndex()
return ["small_url", "regular_url", "full_url"][index]

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Unsplash Image Viewer")
self.setGeometry(100, 100, 1200, 900)

# 메인 위젯과 레이아웃 설정
self.central_widget = DragSelectionWidget(self)
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout(self.central_widget)

# 검색 영역
search_layout = QHBoxLayout()
self.search_input = QLineEdit(self)
self.search_input.setPlaceholderText("검색 키워드를 입력하세요 (예: 자연, 강아지)")
self.search_button = QPushButton("검색", self)
self.search_button.clicked.connect(self.search_images)
search_layout.addWidget(self.search_input)
search_layout.addWidget(self.search_button)
self.layout.addLayout(search_layout)

# 전체 선택 체크박스
select_layout = QHBoxLayout()
self.select_all_checkbox = QCheckBox("전체 선택", self)
self.select_all_checkbox.stateChanged.connect(self.toggle_select_all)
select_layout.addWidget(self.select_all_checkbox)
self.layout.addLayout(select_layout)

# 이미지 그리드 (스크롤 가능)
self.scroll_area = QScrollArea()
self.scroll_widget = QWidget()
self.grid_layout = QGridLayout(self.scroll_widget)
self.scroll_area.setWidget(self.scroll_widget)
self.scroll_area.setWidgetResizable(True)
self.layout.addWidget(self.scroll_area)

# 다운로드 버튼
self.download_button = QPushButton("선택한 이미지 다운로드", self)
self.download_button.clicked.connect(self.show_download_dialog)
self.layout.addWidget(self.download_button)

# 상태 변수
self.image_labels = []
self.selected_images = []
self.current_keyword = ""

def search_images(self):
keyword = self.search_input.text().strip()
if not keyword:
QMessageBox.warning(self, "경고", "검색 키워드를 입력하세요!")
return

for label in self.image_labels:
self.grid_layout.removeWidget(label)
label.deleteLater()
self.image_labels = []
self.selected_images = []
self.current_keyword = keyword
self.select_all_checkbox.setChecked(False)

print(f"검색어: {keyword}")
self.fetcher = ImageFetcher(keyword, max_pages=10)
self.fetcher.imagesFetched.connect(self.display_images)
self.fetcher.start()

def display_images(self, images):
if not images:
QMessageBox.warning(self, "오류", "이미지를 가져오지 못했습니다. API 키나 네트워크를 확인하세요.")
return

for i, (regular_url, small_url, _, full_url) in enumerate(images):
row = i // 6
col = i % 6
image_label = ImageLabel(regular_url, small_url, full_url, self)
self.grid_layout.addWidget(image_label, row, col)
self.image_labels.append(image_label)
print(f"총 {len(images)}개 이미지 로드 완료")

def select_image(self, image_label):
if image_label not in self.selected_images:
self.selected_images.append(image_label)

def deselect_image(self, image_label):
if image_label in self.selected_images:
self.selected_images.remove(image_label)

def toggle_select_all(self, state):
select_all = state == Qt.CheckState.Checked.value
for image_label in self.image_labels:
image_label.set_selected(select_all)
if select_all:
self.selected_images = self.image_labels.copy()
else:
self.selected_images = []

def show_download_dialog(self):
if not self.selected_images:
QMessageBox.warning(self, "경고", "다운로드할 이미지를 선택하세요!")
return

dialog = DownloadDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
self.download_images(dialog.get_selected_quality())

def download_images(self, quality_key):
# 기본 다운로드 폴더
base_download_dir = os.path.join(os.path.dirname(__file__), "Downloaded_Images")
if not os.path.exists(base_download_dir):
os.makedirs(base_download_dir)

# 검색어 기반 하위 폴더
download_dir = os.path.join(base_download_dir, self.current_keyword)
if not os.path.exists(download_dir):
os.makedirs(download_dir)

for image_label in self.selected_images:
url = getattr(image_label, quality_key)
timestamp = int(time.time() * 1000)
filename = os.path.join(download_dir, f"{self.current_keyword}_{timestamp}.jpg")
try:
img_data = requests.get(url).content
with open(filename, 'wb') as f:
f.write(img_data)
print(f"{filename} 다운로드 완료")
except Exception as e:
print(f"{filename} 다운로드 실패: {e}")

QMessageBox.information(self, "성공", f"{len(self.selected_images)}개 이미지 다운로드 완료!")

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

#PYTHON #파이썬 #이미지 #다운로더 #API #unsplash

댓글 쓰기

다음 이전