file 1에 썸네일, 2에 캡처한 파일이 올라가도록 수정

This commit is contained in:
2025-06-27 13:04:46 +09:00
parent 4667079763
commit 0d56d74a25

View File

@ -4,7 +4,7 @@ gnu_autoupload.py
기능:
1. Selenium을 이용해 날씨 정보를 캡처 (weather_capture.py 호출)
2. FTP를 이용해 이미지 업로드
2. FTP를 이용해 이미지 업로드 (썸네일 포함)
3. 그누보드 DB에 게시글 및 첨부파일 정보 자동 등록
"""
@ -21,39 +21,27 @@ import ftputil
from config import DB_CONFIG, FTP_CONFIG, MAIN
# ---------------------------
# 이미지 캡처 관련 함수
# ---------------------------
def capture_image(script_path, output_path, max_attempts=5):
"""
weather_capture.py를 실행해 이미지 파일을 생성
:param script_path: 캡처 스크립트 경로
:param output_path: 기대되는 이미지 파일 경로
:param max_attempts: 최대 재시도 횟수
:return: 성공 여부 (True/False)
"""
for attempt in range(max_attempts):
print(f"[{datetime.now().strftime('%H:%M:%S')}] 캡처 시도 {attempt + 1}/{max_attempts}")
print(f"[{datetime.now().strftime('%H:%M:%S')}] \uac00\uc0ac\uac1c \uc2dc\ub3c4 {attempt + 1}/{max_attempts}")
try:
subprocess.run(['python3', script_path], check=True)
except subprocess.CalledProcessError as e:
print(f"[오류] weather_capture.py 실행 실패: {e}")
print(f"[\uc624\ub958] weather_capture.py \uc2e4\ud589 \uc2e4\ud328: {e}")
if os.path.isfile(output_path):
print(f"[성공] 이미지 캡처 완료: {output_path}")
print(f"[\uc131\uacf5] \uc774\ubbf8\uc9c0 \uce90\ud504 \uc644\ub8cc: {output_path}")
return True
time.sleep(2)
print(f"[실패] {max_attempts}회 시도 후에도 이미지가 생성되지 않았습니다.")
print(f"[\uc2e4\ud328] {max_attempts}\ud68c \uc2dc\ub3c4 \ud6c4\uc5d0\ub3c4 \uc774\ubbf8\uc9c0\uac00 \uc0dd\uc131\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.")
return False
# ---------------------------
# 파일 업로드 및 처리 관련
# ---------------------------
def file_type(ext):
"""
파일 확장자를 기반으로 그누보드용 파일 유형 코드 반환
"""
return {
'gif': '1', 'jpeg': '2', 'jpg': '2', 'png': '3', 'swf': '4',
'psd': '5', 'bmp': '6', 'tif': '7', 'tiff': '7', 'jpc': '9',
@ -61,64 +49,37 @@ def file_type(ext):
'wbmp': '15', 'xbm': '16'
}.get(ext.lower(), '0')
def get_filename(filename):
"""
원본 파일명을 기반으로 해시된 파일명을 생성
"""
ms = datetime.now().microsecond
encoded_name = filename.encode('utf-8')
return f'{ms}_{hashlib.sha1(encoded_name).hexdigest()}'
def file_upload(filename, bf_file):
"""
FTP 서버에 파일 업로드
:param filename: 로컬 경로
:param bf_file: 서버에 저장될 파일명
"""
try:
with ftputil.FTPHost(FTP_CONFIG['HOST'], FTP_CONFIG['USER'], FTP_CONFIG['PASS']) as fh:
fh.chdir(FTP_CONFIG['UPLOAD_DIR'])
fh.upload(filename, bf_file)
print(f"[업로드 완료] {filename}{bf_file}")
print(f"[\uc5c5\ub85c\ub4dc \uc644\ub8cc] {filename}{bf_file}")
return True
except Exception as e:
print(f"[FTP 오류] {type(e).__name__}: {e}")
print(f"[FTP \uc624\ub958] {type(e).__name__}: {e}")
return False
# ---------------------------
# 게시글 작성 함수
# ---------------------------
def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_list=None):
"""
그누보드 DB에 게시글과 파일을 한 트랜잭션으로 삽입
:param board: 게시판 ID
:param subject: 제목
:param content: 내용
:param mb_id: 회원 ID
:param nickname: 작성자 이름
:param ca_name: 카테고리명
:param file_list: 첨부파일 경로 리스트
"""
try:
# 데이터베이스 연결
conn = pymysql.connect(
host=DB_CONFIG['HOST'],
user=DB_CONFIG['USER'],
db=DB_CONFIG['DBNAME'],
password=DB_CONFIG['PASS'],
charset='utf8'
host=DB_CONFIG['HOST'], user=DB_CONFIG['USER'], db=DB_CONFIG['DBNAME'],
password=DB_CONFIG['PASS'], charset='utf8'
)
curs = conn.cursor()
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 게시글 번호(wr_num) 계산
curs.execute(f"SELECT wr_num FROM g5_write_{board}")
wr_num = str(int(curs.fetchone()[0]) - 1)
# 게시글 삽입
curs.execute(f"""INSERT INTO g5_write_{board} SET wr_num = {wr_num},
wr_reply = '', wr_comment = 0, ca_name = %s, wr_option = 'html1', wr_subject = %s,
wr_content = %s, wr_link1 = '', wr_link2 = '', wr_link1_hit = 0, wr_link2_hit = 0,
@ -131,24 +92,19 @@ def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_lis
""",
(ca_name, subject, content, mb_id, nickname, now, now))
# wr_id 조회
curs.execute(f"SELECT wr_id FROM g5_write_{board} ORDER BY wr_id DESC LIMIT 1")
wr_id = str(curs.fetchone()[0])
# wr_parent 업데이트
curs.execute(f"UPDATE g5_write_{board} SET wr_parent = {wr_id} WHERE wr_id = {wr_id}")
# 새글 테이블 등록
curs.execute(f"""INSERT INTO g5_board_new (bo_table, wr_id, wr_parent, bn_datetime, mb_id)
VALUES (%s, %s, %s, %s, %s)""", (board, wr_id, wr_id, now, mb_id))
# 게시글 수 증가
curs.execute(f"SELECT bo_count_write FROM g5_board WHERE bo_table = %s", (board,))
bo_count_write = int(curs.fetchone()[0])
curs.execute(f"UPDATE g5_board SET bo_count_write = %s WHERE bo_table = %s",
(bo_count_write + 1, board))
# 파일 업로드 처리
file_count = 0
if file_list:
for idx, file in enumerate(file_list):
@ -170,48 +126,43 @@ def write_board(board, subject, content, mb_id, nickname, ca_name=None, file_lis
size, width, height, img_type, now))
file_count += 1
else:
print(f"[경고] 파일 업로드 실패: {file}")
print(f"[\uacbd\uace0] \ud30c\uc77c \uc5c5\ub85c\ub4dc \uc2e4\ud328: {file}")
# 첨부파일 수 업데이트
curs.execute(f"UPDATE g5_write_{board} SET wr_file = %s WHERE wr_id = %s", (file_count, wr_id))
# 트랜잭션 커밋 (단 1회)
conn.commit()
print("[완료] 게시글 작성 및 파일 업로드 완료")
print("[\uc644\ub8cc] \uac8c\uc2dc\uae00 \uc791\uc131 \ubc0f \ud30c\uc77c \uc5c5\ub85c\ub4dc \uc644\ub8cc")
except Exception as e:
# 예외 발생 시 롤백
conn.rollback()
print(f"[DB 오류] {type(e).__name__}: {e}")
print(f"[DB \uc624\ub958] {type(e).__name__}: {e}")
finally:
# 연결 종료
conn.close()
# ---------------------------
# 메인 실행 함수
# ---------------------------
def main():
# 파일 경로 및 이름 설정
today = datetime.today().strftime('%Y%m%d')
script_dir = os.path.dirname(os.path.abspath(__file__))
capture_script = os.path.join(script_dir, 'weather_capture.py')
weather_filename = f'weather_capture_{today}.png'
weather_file = os.path.join(script_dir, weather_filename)
# 이미지 생성 시도
thumb_file = os.path.join(script_dir, 'thumb.jpg')
if not os.path.isfile(thumb_file):
print(f"[\uc624\ub958] \uc368\uba58\ub0b4\uc77c \ud30c\uc77c\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc74c: {thumb_file}")
return
if not capture_image(capture_script, weather_file):
return
# 설정값 동적 갱신
FTP_CONFIG['UPLOAD_DIR'] = f"/www/data/file/{MAIN['board']}/"
MAIN['subject'] = f"[{datetime.now().strftime('%Y-%m-%d')}] 날씨 정보"
MAIN['file1'] = MAIN['file2'] = weather_file
MAIN['subject'] = f"[{datetime.now().strftime('%Y-%m-%d')}] \ub0a0\uc528 \uc815\ubcf4"
MAIN['file1'] = thumb_file
MAIN['file2'] = weather_file
file_list = [MAIN['file1']]
file_list = [MAIN['file1'], MAIN['file2']]
# 게시글 작성
write_board(
board=MAIN['board'],
subject=MAIN['subject'],
@ -222,14 +173,12 @@ def main():
file_list=file_list
)
# 캡처 파일 삭제
try:
if os.path.isfile(weather_file):
os.remove(weather_file)
print(f"[삭제 완료] {weather_file}")
print(f"[\uc0ad\uc81c \uc644\ub8cc] {weather_file}")
except Exception as e:
print(f"[삭제 오류] {type(e).__name__}: {e}")
print(f"[\uc0ad\uc81c \uc624\ub958] {type(e).__name__}: {e}")
# ---------------------------
# 스크립트 실행 진입점