그누보드 자동 글 작성 + 멀티 파일 업로드 스크립트 (Python) > 그누보드5 팁자료실

그누보드5 팁자료실

그누보드 자동 글 작성 + 멀티 파일 업로드 스크립트 (Python) 정보

그누보드 자동 글 작성 + 멀티 파일 업로드 스크립트 (Python)

본문

냑 회원님들 안녕하세요? ^-^

 

이번 주말에는 비가 많이 오네요~ 

 

다들 비 피해 없으시기를 기원할게요! :)

 

 

저번에 작성했던 'Python으로 구현한 그누보드 자동 글쓰기 함수'( https://sir.kr/g5_tip/15678 )를 보완하여

 

멀티 파일 업로드까지 가능하도록 업데이트 하였습니다 ^^

 

그누보드 PHP 내장함수를 사용할 수 없기 때문에 해당 함수를 파이썬으로 변환하여 적절히 처리했구요~

 

다만 replace_filename() 함수에서 SHA1 방식 암호화를 하는 부분 중에 사용자 IP는 제외했습니다.

 

참고로 pymysql과 ftputil을 제외하면 Anaconda에 포함된 기본 모듈만 사용했어요 :)

 

 

아래 스크립트는 외부에서 그누보드 DB 및 FTP에 접속하는 것을 전제로 구현되었기 때문에

 

호스팅 또는 VPS에서 DB와 FTP에 외부접속할 수 있도록 설정하셔야 정상적으로 작동합니다.

 

 


import pymysql, ftputil, hashlib, os, sys
from datetime import datetime
from PIL import Image

 
def file_type(x): # 그누보드의 bf_type 값을 반환하는 함수입니다. (디폴트 : 0)
    return {'gif' : '1', 'jpeg' : '2', 'jpg' : '2', 'png' : '3', 'swf' : '4', 'psd' : '5',
            'bmp' : '6', 'tif' : '7', 'tiff' : '7', 'jpc' : '9', 'jp2' : '10', 'jpx' : '11',
            'jb2' : '12', 'swc' : '13', 'iff' : '14', 'wbmp' : '15', 'xbm' : '16'}.get(x.lower(), '0')

 
def file_upload(filename, bf_file): # FTP를 이용하여 파일을 업로드하는 함수입니다.
    with ftputil.FTPHost('URL을입력하세요', 'FTP계정명을입력하세요', 'FTP비번을입력하세요') as fh:
        fh.chdir('업로드할디렉토리를입력하세요ex./web/data/file/board')
        fh.upload(filename, bf_file, callback = None)
    return

 
def get_filename(filename): # 파일명을 변환하는 함수입니다.
    ms = datetime.now().microsecond
    encoded_name = filename.encode('utf-8')
    result = f'{ms}_{hashlib.sha1(encoded_name).hexdigest()}'
    return result

 
def board_write(board, subject, content, mb_id, nickname, file_list = None):
    # MySQL connection 및 cursor 생성
    conn = pymysql.connect(host = '연결할URL을입력하세요', 
                           user = 'MySQL유저명을입력하세요', 
                           password = 'MySQL비번을입력하세요',
                           db = 'MySQL디비명을입력하세요', 
                           charset = 'utf8')
    curs = conn.cursor()
 
    # 작성글 INSERT
    sql = f"select wr_num from g5_write_{board}"
    curs.execute(sql)
    wr_num = str(int(curs.fetchone()[0]) - 1)
    print(wr_num)
    now = datetime.today().strftime('%Y-%m-%d %H:%M:%S') # 그누보드의 날짜 형식 준수 (ex: 2021-04-05 23:45:15)
    sql = f"insert into g5_write_{board} set wr_num = {wr_num}, \
          wr_reply = '', wr_comment = 0, ca_name = '', wr_option = 'html1', wr_subject = '{subject}', \
          wr_content = '{content}', wr_link1 = '', wr_link2 = '', \
          wr_link1_hit = 0, wr_link2_hit = 0, wr_hit = 1, wr_good = 0, wr_nogood = 0, \
          mb_id = '{mb_id}', wr_password = '', wr_name = '{nickname}', wr_email = '', wr_homepage = '', \
          wr_datetime = '{now}', wr_last = '{now}', wr_ip = '111.111.111.111', \
          wr_1 = '', wr_2 = '', wr_3 = '', wr_4 = '', wr_5 = '', \
          wr_6 = '', wr_7 = '', wr_8 = '', wr_9 = '', wr_10 = '', \
          wr_comment_reply = '', wr_facebook_user = '', wr_twitter_user = '', \
          as_re_name = '', as_tag = '', as_map = '', as_icon = '', as_thumb = '', as_video = ''"
    curs.execute(sql)
 
    # 부모 아이디에 UPDATE
    sql = f"select wr_id from g5_write_{board}"
    curs.execute(sql)
    wr_id = str(curs.fetchall()[-1][0])
    print(f"wr_id : {wr_id}")
    sql = f"update g5_write_{board} set wr_parent = {wr_id} where wr_id = {wr_id}"
    curs.execute(sql)
 
    # 새글 INSERT
    sql = f"insert into g5_board_new ( bo_table, wr_id, wr_parent, bn_datetime, mb_id ) values \
          ( '{board}', '{wr_id}', '{wr_id}', '{now}', '{mb_id}' )"
    curs.execute(sql)
 
    # 게시글 1 증가
    sql = f"select bo_count_write from g5_board where bo_table = '{board}'"
    curs.execute(sql)
    bo_count_write = str(int(curs.fetchone()[0]))
    print(curs.fetchall())
    print(bo_count_write)
    sql = f"update g5_board set bo_count_write = {bo_count_write} + 1 where bo_table = '{board}'"
    curs.execute(sql)
 
    # 파일 업로드 및 관련 정보를 테이블에 저장
    if not file_list or file_list == [''] or file_list == []: # 첨부파일이 없는 경우에는 스크립트를 중단합니다.
        conn.close()
        sys.exit()
 
    file_count = len(file_list)
    for cnt, file in enumerate(file_list):
        ext = os.path.splitext(file)[1].lstrip('.')
        bf_file = f'{get_filename(file)}.{ext}'
        file_upload(file, bf_file)
        type = file_type(ext)
        if type != '0': # 이미지 파일의 경우 가로 및 세로를 구하고, 그 외의 경우에는 0을 대입합니다.
            im = Image.open(file)
            width, height = im.size
        else:
            width, height = 0, 0
        size = os.path.getsize(file)
        sql = f"insert into g5_board_file set bo_table = '{board}', wr_id = '{wr_id}', \
              bf_no = '{cnt}', bf_source = '{file}', bf_file = '{bf_file}', \
              bf_content = '', bf_download = 0, bf_filesize = '{size}', \
              bf_width = '{width}', bf_height = '{height}', bf_type = '{type}', bf_datetime = '{now}'"
        curs.execute(sql)
    
    # 파일의 개수를 게시물에 업데이트
    sql = f"update g5_write_board set wr_file = '{file_count}' where wr_id = '{wr_id}'"
    curs.execute(sql)
 
    # MySQL connection 닫기
    conn.close()
    return

 
def main():
    board = '게시판명을입력하세요'
    subject = '제목을입력하세요'
    content = '내용을입력하세요HTML태그도가능합니다'
    mb_id = '아이디를입력하세요'
    nickname = '닉네임을입력하세요'
    file_list = ['업로드할파일명을입력하세요', '업로드할파일명을입력하세요']
    board_write(board, subject, content, mb_id, nickname, file_list)

 
if __name__ == "__main__":
    main()

 

 

위 스크립트를 활용하여 3개의 파일(PNG, GIF, PY)을 업로드한 결과는 다음과 같습니다 ^^

 

영문이나 숫자가 아닌 한글로 된 파일명도 정상적으로 업로드되는 것을 확인했어요~

 

아미나에서 테스트하였지만 그누보드 5.4에서도 대동소이할 것으로 생각되네요 :)

 

 

3666978703_1621123092.7271.png

(냥냥펀치!)

 

 

테스트해보니 작성자명을 계정의 실제 닉네임과 달리 적용한 경우에

 

위 함수로 글을 올린 후 로그인하여 글을 수정하면 해당 계정의 실제 닉네임으로 변경되는 점을 주의하셔야 됩니다!

 

 

crontab에 넣고 장기적으로 실사용하시려면 다음과 같은 부분을 보완하시는 것을 권장합니다 ^^

 

1. 오류 처리

 

파일 업로드 실패 등의 경우에 글과 첨부파일을 삭제하고 sys.exit() 하도록 처리하면 좋을 것 같네요.

 

 

2. 보안

 

사이트 운영자가 직접 글 내용과 이미지를 선별하여 사용할 것이라면 별다른 보안 이슈는 없겠지만,

 

명랑폐인 님께서 올려주신 '게시판 파싱후 글등록 처리 함수'을 참고하여 조금 더 보완하시면 도움이 될듯요~

 

https://sir.kr/g5_tip/6977

 

만약 타 사이트에서 파싱한 결과물을 위 함수를 이용하여 그대로 올리는 목적으로 사용하시려면

 

SQL injection, steganography 등 기법에도 대응할 수 있도록 보완해야 안전할 것 같습니다 ㅎㄷㄷ

 

 

이상 허접한 스크립트인데 읽어주셔서 감사합니다!

 

다음에는 위 함수를 활용하여 브라우저에 접속하지 않은 상태에서

 

곧바로 글 작성 및 첨부파일 업로드를 할 수 있는 GUI 프로그램을 작성해볼게요~ 

 

그럼 냑 회원님들 다들 좋은 주말 되시고, 내일까지 비가 온다니 아침에 우산 꼭 챙기세요 ^-^

 

감사합니다!!

추천
12

댓글 11개

저는 한 서버에 그누2개를 사용하는데 1번 그누 게시글을 자동으로 2번 게시판에 어미지를 포함해서 올라가게 하려면 이것을 사용하면 될것 같은데 어떻게 사용하면 되는지요?

물론 디비에서 다운받아서 올리면 되는데 이게 훨씬 편할 것 같습니다
제가 잘못 이해를 했는지 모르지만요?

감사합니다
안녕하세요? ^^
말씀하신 내용이 그누보드를 이용한 A 사이트와 B 사이트를 운영 중이신데,
A 사이트의 게시판에 누군가 글을 작성하면
자동으로 B 사이트에도 글이 작성되도록 하려는 용도이신거죠? :)

그러한 용도라면...
(1) crontab 등을 활용하여 적절한 시간 간격으로 A 사이트 게시판을 크롤링한 후에,
(2) B 사이트 게시판에 위 스크립트를 활용하여 올리시면 됩니다.

그런데 (1)에 해당하는 부분을 별도로 구현하셔야 되기 때문에,
아쉽게도 위 스크립트만으로는 원하시는 결과물을 얻어낼 수는 없습니다 ㅠㅠ

충분한 설명이 되셨는지요? :)
그럼 좋은 휴일 보내시길 기원합니다!
옙 원하시는 결과를 구현하는 방법이 여러 가지가 있을 것 같습니다 ^-^
SIR에는 저보다 고수님들이 많이 계시니 해당 내용을 질문 게시판에 올리시면
최선의 방법을 찾으실 수 있을 것 같네요 :)
일회적으로 크롤링하는 것과, 장기적으로 꾸준히 크롤링하는 것은 상당히 다릅니다.
저는 파이썬이 편해서 파이썬을 많이 활용하는 편이지만,
아마도 다른 분들께서는 굳이 파이썬을 사용하여 크롤링으로 해결하기보다는 다른 더 좋은 방법을 권하실 것 같습니다.
그럼 문의하신 내용도 잘 해결되시고, 가정에 건강이 늘 함께 하시기를 기원합니다!
티스토리 글이랑, 첨부 긁어올수 있나요?

제 블로그가 티스토리에 글이 몇개 있는데
그누보드로 마이그레이션 하고 싶거든요
전체 10 |RSS
그누보드5 팁자료실 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT