• 목록
  • 아래로

안녕하세요? ^-^

 

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

 

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

 

 

저번에 '소스 공유' 게시판에 작성했던 'Python으로 구현한 그누보드 자동 글쓰기 함수'( https://studyforus.com/share/808613 )를 보완하여

 

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

 

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

 

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

 

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

 

 

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

 

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

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 = 00
        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에서도 대동소이할 것으로 생각되네요 :)

 

 

img 20210516 084554.png.jpg

(냥냥펀치!)

 

 

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

 

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

 

 

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

 

1. 오류 처리

 

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

 

 

2. 보안

 

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

 

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

 

https://sir.kr/g5_tip/6977

 

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

 

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

 

 

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

 

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

 

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

 

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

 

감사합니다!!

 

알피쥐님 포함 6명이 추천

작성자
이니스프리 119 Lv. (2%) 4400190/115200000EXP

Make StudyForUs Great Again!

 

CSVpuymXAAAVVpd.jpg

댓글 1

알피쥐
오오 좋은 글 감사합니다.
comment menu
2023.02.24. 17:16

신고

"알피쥐님의 댓글"

이 댓글을 신고 하시겠습니까?

권한이 없습니다.
번호 제목 글쓴이 날짜 조회 수
29 [디지털포렌식전문가] 제21회 필기시험 합격 후기 9 image 이니스프리 이니스프리 23.10.29.16:11 3180
28 [Python] GIF 파일에 프로그레스바 삽입하기! (Adding progress bar into GIF) image 이니스프리 이니스프리 22.05.14.13:14 13073
[Python] 그누보드 자동 글 작성 + 멀티 파일 업로드 스크립트 1 image 이니스프리 이니스프리 21.05.16.09:32 24004
26 0. 행의 분리 및 결합 / 멀티라인 문자열 image 이니스프리 이니스프리 21.04.18.11:53 692
25 [Selenium] proxy를 사용하지 않고 개발자도구에서 Network 탭의 로그를 얻기 image 이니스프리 이니스프리 21.03.06.23:35 1892
24 [번외편 - 한컴한글] 스마트한 문서 작성을 위한 팁 (작성 중) 이니스프리 이니스프리 20.08.08.13:50 625
23 [Requests-HTML] Requests와 비교할 때의 장점! (네이버 뉴스 등 크롤링) 8 image 이니스프리 이니스프리 20.05.14.19:08 1776
22 22. [OpenPyXL] 엑셀 문서 저장하기 / 시트 추가하기 / 셀에 입력하기 14 image 이니스프리 이니스프리 20.02.02.00:46 5797
21 21. [OpenPyXL] 엑셀 문서를 열고 시트에서 셀의 값을 얻기 3 image 이니스프리 이니스프리 20.02.01.23:46 1561
20 [BeautifulSoup] 자식태그를 제거하기 - .decompose() & .extract() 10 image 이니스프리 이니스프리 20.01.16.00:07 9524
19 [python-telegram-bot] 4096자 글자수 제한을 우회하는 방법 image 이니스프리 이니스프리 20.01.12.11:25 2527
18 [Requests] Selenium을 이용한 Cloudflare의 우회 8 image 이니스프리 이니스프리 20.01.08.19:51 6702
17 9. [정리] 파이써닉한 파이썬 문법 팁 for COS Pro image 이니스프리 이니스프리 20.01.04.23:47 1231
16 [번외편] 네이버 동영상에서 자막을 파일로 추출하는 방법 2 image 이니스프리 이니스프리 19.12.25.22:34 6079
15 4. 문자열 처리 (2) - 문자열 조작에 대한 기본함수 및 메서드 1 image 이니스프리 이니스프리 19.12.12.02:27 807
14 6. 리스트와 관련된 기본함수 및 메서드 7 image 이니스프리 이니스프리 19.12.10.21:16 2294
13 3. 문자열 처리 (1) - 문자열 접근 및 검색방법 4 image 이니스프리 이니스프리 19.12.09.20:00 1441
12 [Selenium] Requests의 session을 Selenium으로 보내기 image 이니스프리 이니스프리 19.12.07.14:17 4996
11 1. 반복문 (1) - while 문 7 image 이니스프리 이니스프리 19.12.06.20:50 2739
10 (序) Python 강좌를 시작하며... 2 image 이니스프리 이니스프리 19.12.05.21:55 744