Last active
January 23, 2024 03:16
-
-
Save Leuconoe/21f6a07f50389c4de1ec127944af7008 to your computer and use it in GitHub Desktop.
KidsnoteDownloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#thanks to goodhobak from https://www.clien.net/ | |
#requre: requests Pillow piexif | |
#use: | |
#1. get json from api in webpage | |
#2. save json | |
#commit : 파일의 생성일, 수정일 수정 | |
import json | |
import os | |
import requests | |
from PIL import Image | |
import piexif | |
from datetime import datetime, timedelta | |
from xml.etree import ElementTree as ET | |
from datetime import datetime | |
import os | |
import pywintypes, win32file, win32con | |
def convert_to_degrees(value): | |
"""Convert decimal coordinate to degrees, minutes, and seconds tuple.""" | |
degrees = int(value) | |
minutes = int((value - degrees) * 60) | |
seconds = (value - degrees - minutes / 60) * 3600 | |
seconds_numerator = int(seconds * 100) | |
seconds_denominator = 100 | |
return ((degrees, 1), (minutes, 1), (seconds_numerator, seconds_denominator)) | |
def add_exif_data(image_path, title, content, modified_time): | |
# Load the image | |
img = Image.open(image_path) | |
# Check if the image has existing EXIF data | |
if 'exif' in img.info: | |
exif_dict = piexif.load(img.info['exif']) | |
else: | |
exif_dict = {"0th": {}, "Exif": {}, "GPS": {}, "1st": {}, "thumbnail": None} | |
# Prepare the formatted time | |
formatted_time = modified_time.strftime("%Y:%m:%d %H:%M:%S") | |
# Check if DateTimeOriginal exists and if it matches the intended value | |
existing_date_time_original = exif_dict['Exif'].get(piexif.ExifIFD.DateTimeOriginal, None) | |
if existing_date_time_original and existing_date_time_original != formatted_time: | |
#print(f"Skipping {image_path}: DateTimeOriginal does not match the intended value.") | |
img.close() # Close the image and skip further processing | |
return | |
# Update the datetime fields | |
exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = formatted_time | |
exif_dict['Exif'][piexif.ExifIFD.DateTimeDigitized] = formatted_time | |
exif_dict['0th'][piexif.ImageIFD.DateTime] = formatted_time | |
# User comment | |
user_comment = f"Title: {title}\nContent: {content}" | |
encoded_comment = user_comment.encode('utf-8') | |
exif_dict['0th'].setdefault(piexif.ImageIFD.ImageDescription, encoded_comment) | |
# Convert EXIF data to bytes and save the image | |
exif_bytes = piexif.dump(exif_dict) | |
img.save(image_path, exif=exif_bytes) | |
# Close the image | |
img.close() | |
def add_xmp_data(image_path, title, content, modified_time): | |
# Open the image | |
img = Image.open(image_path) | |
# Create XMP data | |
xmp_template = f""" | |
<x:xmpmeta xmlns:x="adobe:ns:meta/"> | |
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> | |
<rdf:Description rdf:about="" | |
xmlns:dc="http://purl.org/dc/elements/1.1/" | |
xmlns:xmp="http://ns.adobe.com/xap/1.0/"> | |
<dc:title>{title}</dc:title> | |
<dc:description>{content}</dc:description> | |
<xmp:ModifyDate>{modified_time.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:ModifyDate> | |
<xmp:CreateDate>{modified_time.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:CreateDate> | |
</rdf:Description> | |
</rdf:RDF> | |
</x:xmpmeta> | |
""" | |
xmp_data = bytes(xmp_template, 'utf-8') | |
# Check if the image has existing XMP data and append the new data | |
if "APP1" in img.info and b'http://ns.adobe.com/xap/1.0/' in img.info["APP1"]: | |
existing_xmp_index = img.info["APP1"].find(b'http://ns.adobe.com/xap/1.0/') | |
if existing_xmp_index != -1: | |
# Extract existing XMP data and create a combined XMP | |
existing_xmp_data = img.info["APP1"][existing_xmp_index:] | |
combined_xmp_data = existing_xmp_data.strip(b' ') + b' ' + xmp_data | |
else: | |
combined_xmp_data = xmp_data | |
else: | |
combined_xmp_data = xmp_data | |
# Save the image with new metadata | |
img.save(image_path, "jpeg", exif=img.info.get('exif'), xmp=combined_xmp_data) | |
# Close the image | |
img.close() | |
def change_file_times(filename, created_time, modified_time): | |
ctime = pywintypes.Time(created_time) | |
mtime = pywintypes.Time(modified_time) | |
handle = win32file.CreateFile(filename, win32con.GENERIC_WRITE, 0, None, win32con.OPEN_EXISTING, 0, None) | |
win32file.SetFileTime(handle, ctime, None, mtime) | |
handle.Close() | |
# 파일 읽기 | |
with open("album.json", "r", encoding='utf-8') as file: | |
data = json.load(file) | |
# 앨범 처리 | |
for album in data['results']: | |
# 폴더 생성 | |
date_str = album['created'][:10] # "YYYY-MM-DD" | |
month_str = album['created'][:7] # "YYYY-MM" | |
folder_name = f"Album\Album-{month_str}\{date_str}" | |
os.makedirs(folder_name, exist_ok=True) | |
# 앨범 설명 저장 | |
description_path = os.path.join(folder_name, "album-description.txt") | |
if os.path.exists(description_path): | |
#print (f"'{date_str}' is exist"); | |
continue | |
created_time_utc = datetime.strptime(album['created'], "%Y-%m-%dT%H:%M:%S.%fZ") | |
modified_time_utc = datetime.strptime(album['modified'], "%Y-%m-%dT%H:%M:%S.%fZ") | |
# Add 9 hours to convert UTC to Seoul time (UTC+09:00) | |
seoul_offset = timedelta(hours=9) | |
created_time = created_time_utc + seoul_offset | |
modified_time = modified_time_utc + seoul_offset | |
file = open(os.path.join(description_path), "w", encoding='utf-8') | |
file.write(f"Title: {album['title']}\n") | |
file.write(f"Content: {album['content']}\n") | |
file.write(f"json: {album}\n") | |
file.close() | |
# Change times | |
change_file_times(description_path, created_time, modified_time) | |
# 비디오 처리 | |
if album['attached_video']: | |
video_url = album['attached_video'] | |
video_response = requests.get(video_url) | |
video_path = os.path.join(folder_name, f"KidsNote_Vidio_{album['id']}.MP4") | |
file = open(video_path, "wb"); | |
file.write(video_response.content) | |
file.close(); | |
# Change times | |
change_file_times(video_path, created_time, modified_time) | |
# 이미지 처리 | |
for index, image in enumerate(album['attached_images'], start=1): | |
image_url = image['original'] | |
image_response = requests.get(image_url) | |
image_path = os.path.join(folder_name, f"KidsNote_Photo_{date_str}-{index}.jpg") | |
file = open(image_path, "wb") | |
file.write(image_response.content) | |
file.close(); | |
# Change times | |
change_file_times(image_path, created_time, modified_time) | |
# EXIF 데이터 추가 | |
try: | |
add_exif_data(image_path, album['title'], album['content'], modified_time) | |
add_xmp_data(image_path, album['title'], album['content'], modified_time) | |
except Exception as e: | |
print(f"EXIF error for '{folder_name}': {e}") | |
print(f"Album '{folder_name}' processed.") | |
print("All albums have been processed.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#thanks to goodhobak from https://www.clien.net/ | |
#requre: requests Pillow piexif | |
#use: | |
#1. get json from api in webpage | |
#2. save json | |
import json | |
import os | |
import requests | |
from PIL import Image | |
from PIL.ExifTags import TAGS, GPSTAGS | |
import datetime | |
import piexif | |
from xml.etree import ElementTree as ET | |
def convert_to_degrees(value): | |
"""Convert decimal coordinate to degrees, minutes, and seconds tuple.""" | |
degrees = int(value) | |
minutes = int((value - degrees) * 60) | |
seconds = (value - degrees - minutes / 60) * 3600 | |
seconds_numerator = int(seconds * 100) | |
seconds_denominator = 100 | |
return ((degrees, 1), (minutes, 1), (seconds_numerator, seconds_denominator)) | |
def add_exif_data(image_path, title, content, location): | |
# Load the image | |
img = Image.open(image_path) | |
# Check if the image has 'exif' data | |
if 'exif' in img.info: | |
exif_dict = piexif.load(img.info['exif']) | |
else: | |
exif_dict = {"0th": {}, "Exif": {}, "GPS": {}, "1st": {}, "thumbnail": None} | |
# GPS coordinates | |
latitude, longitude = map(float, location.split(',')) | |
exif_dict['GPS'][piexif.GPSIFD.GPSLatitudeRef] = 'N' if latitude >= 0 else 'S' | |
exif_dict['GPS'][piexif.GPSIFD.GPSLongitudeRef] = 'E' if longitude >= 0 else 'W' | |
exif_dict['GPS'][piexif.GPSIFD.GPSLatitude] = convert_to_degrees(abs(latitude)) | |
exif_dict['GPS'][piexif.GPSIFD.GPSLongitude] = convert_to_degrees(abs(longitude)) | |
# User comment | |
user_comment = f"Title: {title}\nContent: {content}" | |
encoded_comment = user_comment.encode('utf-8') | |
exif_dict['0th'][piexif.ImageIFD.ImageDescription] = encoded_comment | |
# Convert EXIF data to bytes and save the image | |
exif_bytes = piexif.dump(exif_dict) | |
img.save(image_path, exif=exif_bytes) | |
# Close the image | |
img.close() | |
def create_xmp_data(title, content, location): | |
xmp_template = f""" | |
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> | |
<rdf:Description rdf:about="" | |
xmlns:dc="http://purl.org/dc/elements/1.1/"> | |
<dc:title>{title}</dc:title> | |
<dc:description>{content}</dc:description> | |
<dc:location>{location}</dc:location> | |
</rdf:Description> | |
</rdf:RDF> | |
""" | |
return xmp_template | |
def add_xmp_data(image_path, title, content, location): | |
# Open the image | |
img = Image.open(image_path) | |
xmp_data = create_xmp_data(title, content, location) | |
xmp_bytes = xmp_data.encode('utf-8') | |
# Check if the image has existing metadata and append XMP data | |
if "APP1" in img.info: | |
existing_metadata = img.info["APP1"] | |
new_metadata = existing_metadata + b'\n' + xmp_bytes | |
else: | |
new_metadata = xmp_bytes | |
# Save the image with new metadata | |
img.save(image_path, "jpeg", exif=new_metadata) | |
# Close the image | |
img.close() | |
# 파일 읽기 | |
with open("report.json", "r", encoding='utf-8') as file: | |
data = json.load(file) | |
# 앨범 처리 | |
for report in data['results']: | |
# 폴더 생성 | |
date_str = report['created'][:10] # "YYYY-MM-DD" | |
month_str = report['created'][:7] # "YYYY-MM" | |
folder_name = f"Report\Report-{month_str}\{date_str}" | |
os.makedirs(folder_name, exist_ok=True) | |
# 앨범 설명 저장 | |
description_path = os.path.join(folder_name, "report-description.txt") | |
if os.path.exists(description_path): | |
print (f"'{date_str}' is exist"); | |
continue | |
with open(os.path.join(description_path), "w", encoding='utf-8') as file: | |
file.write(f"Title: {report['class_name']}-{report['child_name']}\n") | |
file.write(f"Weather: {report['weather']}\n") | |
file.write(f"Content: {report['content']}\n") | |
# 비디오 처리 | |
if report['attached_video']: | |
video_url = report['attached_video'] | |
video_response = requests.get(video_url) | |
video_path = os.path.join(folder_name, f"V_{report['id']}.MP4") | |
with open(video_path, "wb") as file: | |
file.write(video_response.content) | |
# 이미지 처리 | |
for index, image in enumerate(report['attached_images'], start=1): | |
image_url = image['original'] | |
image_response = requests.get(image_url) | |
image_path = os.path.join(folder_name, f"P_{date_str}-{index}.jpg") | |
with open(image_path, "wb") as file: | |
file.write(image_response.content) | |
try: | |
# EXIF 데이터 추가 | |
add_exif_data(image_path, report['child_name'], report['content'], "55.55555, 555.5555") | |
# XMP 데이터 추가 | |
#add_xmp_data(image_path, report['child_name'], report['content'], "55.5555, 555.555555") | |
except: | |
print(f"'{folder_name}' : exif error") | |
print(f"Report '{folder_name}' processed.") | |
print("All reports have been processed.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment