PIL이라는 라이브러리와 natsort라는 라이브러를 사용하여,

 

 

아주 쉽게 PDF파일을 만들어내는 스크립트.

import os
from PIL import Image
import natsort


realpath = "/Users/1111964/Downloads/images"
originimages = natsort.natsorted(os.listdir(realpath))
images = []

for i in originimages:
    try:
       print (i)
       print (Image.open (realpath + '/' + i))
       images.append(Image.open (realpath + '/' + i))
    except:
       print ("error : " + i)


images[0].save(
    realpath +"/out.pdf", "PDF", resolution=100.0, save_all=True, append_images=images[1:]
)

 

ㅇ 당연한것이지만 image, narsort에 대한 PIP 라이브러리 설치가 선행되어야 한다.

ㅇ 이미지 파일들이 모아놓은 폴더 주소를 딴다. 여기서는 맥북 기준으로 "/Users/1111964/Downloads/images"를 사용했다. 윈도우면 "C:\\Users\\USER\\Downloads" 대략 이런식으로 폴더 지정 하면 된다"

 

 

ㅇ이름이나 저장경로를 바꾸고 싶으면 realpath +"/out.pdf" 이부분을 손봐주시면 되겠다. 여기는

이미지가 모여있는 폴더에서 out.pdf라는 파일로 저장하겠다는 것이다.

 

 

 

 

 

텔레그램은 여러가지 범죄수단으로 악명이 높지만

사실은 매우 훌륭한 메신져서비스이다.

 

가볍고, 성능이 좋으며, 메세지도 서버에서 거의 무제한 저장(한계를 정확히 모름)한다.

심지어 윈도우, 맥의 데스크탑 앱도 매우 성능이 좋으며, 모바일과 메세지를 동기화한다.

 

이정도 수준은 카카오톡도 라인도 못한다.

그리고 api 및 커스텀개발이 매우 잘되어있는 메신저이다.

 

이것 저것 Bot들이 텔레그램으로 많이 쓰이는 이유이기도 하다.

 

 

 

 

검색해보니 블로그에 텔레그램 봇 만들기 정보가 여러가지 있었는데, 대부분 동작을 안해서 애를 먹었다

stack overflow를 대충 살펴보니, 옛날방식이라, 파이썬 텔레그램 모듈에서 더이상 작동하지 않는 거라고.,.

 

그러면 방법이 없나?

 

텔레그램 봇 모듈의 사이트의 문서를 보면

최신식으로 봇을 만들수 있는 동작이 소개되어있다.

https://docs.python-telegram-bot.org/en/v20.6/examples.echobot.html

 

echobot.py - python-telegram-bot v20.6

Previous deeplinking.py

docs.python-telegram-bot.org

 

그래서 거기있는 샘플 수정해다가

지난번 만들어둔

modgpt4라는 모듈 스크립트를 기능으로 하는

다음과 같은 텔레그램 봇 서버 스크립트를 만듬

 

 

모듈은 

python-telegram-bot 이란 놈을 설치해야 한다. (걍 telegram이 아님)

 

cmd/터미널 명령 예시

 

pip3 install python-telegram-bot

 

 

그다음

 

아래의 텔레그램 봇 스크립트와

callgpt4라고 gpt를 호출하는 모듈 스크립트가 필요하다

import logging
import callgpt4  #내가 만든 gpt4호출 모듈
from telegram import __version__ as TG_VER
token = "63525숫자647:AAFnJM어쩌고 당신이 만든 대화방의 토큰"


try:
    from telegram import __version_info__
except ImportError:
    __version_info__ = (0, 0, 0, 0, 0)  # type: ignore[assignment]

if __version_info__ < (20, 0, 0, "alpha", 1):
    raise RuntimeError(
        f"This example is not compatible with your current PTB version {TG_VER}. To view the "
        f"{TG_VER} version of this example, "
        f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
    )
from telegram import ForceReply, Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters

# Enable logging
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
# set higher logging level for httpx to avoid all GET and POST requests being logged
logging.getLogger("httpx").setLevel(logging.WARNING)

logger = logging.getLogger(__name__)


# Define a few command handlers. These usually take the two arguments update and
# context.
# /start로 대화방을 가동시키는 경우 봇의 첫 메세지
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Send a message when the command /start is issued."""
    user = update.effective_user
    await update.message.reply_html(
        rf"안 {user.mention_html()}!, 나는 chatgpt 메신저야",
        reply_markup=ForceReply(selective=True),
    )

#입력된 메세지로,  modgpt4 (gpt4 api를 호출하여 답변을 얻은 모듈) 모듈을 사용
async def gpt(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """gpt모듈을 호출하는것."""
    print (update.message.text)
    await update.message.reply_text("......") #gpt4 모듈이 응답을 준비하는동한 메세지로 ......을 보냄
    userPrompt = update.message.text
    gptresult = callgpt4.Command(userPrompt)
    await update.message.reply_text(gptresult) #gpt4모듈의 답변을 메세지로 보냄


#위의 함수들을 종합하여 텔레그램에 커맨드와 답변을 처리하는 영역

def main() -> None:
    """Start the bot."""
    # Create the Application and pass it your bot's token.
    application = Application.builder().token(token).build()

    # on different commands - answer in Telegram   # /start등 /어쩌고로 지정된 액션을 받아들여, 해당 함수(start)를 호출 동작실행 시키는 커맨드 핸들러
    application.add_handler(CommandHandler("start", start))

    # on non command i.e message - echo the message on Telegram
    application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, gpt)) #텔레그램 user messager를 받아 해당 함수(gpt)에 메세지 input을 넣을수 있는 메세지 핸들러

    # Run the bot until the user presses Ctrl-C
    application.run_polling(allowed_updates=Update.ALL_TYPES)


if __name__ == "__main__":
    main()

* 일단 텔레그램 메신저에서 Bot을 만들고, 텔레그램 Bot 대화방을 생성한뒤 해당 대화방 토큰을 얻어야 한다.

해당 방법은.. 남들이 잘 설명해둔것 같아 아래 링크 참고

https://chancoding.tistory.com/149

 

[Python] 파이썬으로 나만의 텔레그램 봇 만들기

파이썬을 활용한 나만의 텔레그램 봇을 만들어보겠습니다. 자신만의 필요한 알림을 위해서나 스케줄 관리를 위해서 텔레그램 봇을 활용할 수 있습니다. 시간이 되면 딱딱 필요한 내용들을 메시

chancoding.tistory.com

그러나 여기서 하단에 만든 텔레그램봇 파이썬 스크립트 샘플은

아까 말한대로 구버전이라 동작하지 않을것이다.

 

 

 

* gpt답변을 만드는 함수를 위해, gpt4를 호출하는 모듈이 필요하다

callgpt4라는 스크립트 모듈을 아래와 같이 만들어서, 위 스크립트와 같은 폴더에 두자

import os
import openai
import datetime
openai.api_key = os.getenv("OPENAI_API_KEY") #환경변수로 local에 저장된 api key를 가져오기

model = "gpt-4"     # 모델선택 gpt-4, gpt-4-0314, gpt-4-32k, gpt-4-32k-0314, gpt-3.5-turbo, gpt-3.5-turbo-0301

def Command(Prompt):

  completion = openai.ChatCompletion.create(
    model=model,
    temperature=0,
    messages=[
      {"role": "user", "content": Prompt}
    ]
  )
  result = completion.choices[0]
  message = result.message.content
  print(datetime.datetime.now())
  return message


# 이건 gpt4 호출하는 이 스크립트 정상동작여부 테스트용
#print ("test :", Command("너는 gpt4가 맞아??"))

이렇게 만들어두면, 텔레그램 서버처럼 다른 스크립트에서 callgpt4.Command("input값)으로 gpt4에 input값으로 호출하여

"챗gpt의 응답 message"를 리턴받을수 있게 된다.

 

* openai의 api key가 필요하다. 오픈 ai에서 직접 apikey를 발급받아 쓰면된다/

환경변수로 local에 저장하는 편이 스크립트에 직접 apikey를 쓰는것보다 상대적으로 안전하다.

유료api이기때문에 웹에 스크립트가 공유되어 apikey가 노출되면 골치아파짐, gpt-3는 호출 1건당 토큰이 많더라도 계산이 안될 정도로 저렴한데,  gpt-4는 상당히 비쌈

 

 

 

 

그럼 잘 동작하느냐

텔레그램 서버 스크립트를 run 시키고, 스크립트 돌아가는 동안

텔레그램 bot대화방에서  대화를 입력하면~ chatgpt모듈 (gpt4) 답변을 잘 주신다~~

 

 

 

 

 

업비트에서 코인이름으로 가격조회하기 실급

 

지난번에 이어서

 

업비트의 코인이름으로 정보/가격 조회하는 프로그래밍을 해보자,

귀찮은 관계로 통째로 소스를 붙이고 주석으로 설명해두었다

 

import requests


#### 모든 코인들의 코드명을 알아보자

url = "https://api.upbit.com/v1/market/all"

response = requests.get(url)
market_list = response.json()

## 모든 코인들의 json결과
print (market_list)


## {코인이름 : 코드명}을 담아낼 dictionary 그릇만들기
market_dict = {}

## 빈 그릇에 json의 코인이름:코드명만 뽑아 dictionary 형태로 넣는다
for i in market_list:
    if i['market'].split("-")[0] == "KRW":  # KRW(한화) 가격정보의 코드명만 가져온다
        market_dict[i['korean_name']]=i['market']  #KRW 조건의 코인이름:코드명을 dictionary로 저장
        print (i['market'])
    else:                       # KRW가 아닌 코드명은 버린다
        print ('ignore')
print (market_dict)

######### 한글만 넣어도 가격이 나오는 API 처리 ###########

coin_name = "리플"  #여기다가 업비트에서 지원하는 코드명을 변수로 쓰면, 매칭된 코드명으로 코인정보+가격을 조회해 올 것이다.

coin_code_name = market_dict[coin_name]
coin_info_url = "https://api.upbit.com/v1/ticker?markets=" + str(coin_code_name)
coin_info_response = requests.get(coin_info_url)
coin_info_result = coin_info_response.json()[0]

print ("정보: ", coin_info_result)
print ("시작가: ", coin_info_result['opening_price'])
print ("현재거래가: ", coin_info_result['trade_price'])

API get method를 알아보자,

개발자가 아니어도 유용하게 API를 활용할수 있는 아주 좋은 방법,

 

requests와 json만 다룬다면 여러가지 API를 get method로 잘 조회해 올 수 있다.

우선 requests부터,

 

준비물 : python3 이상과, requests 모듈

API : 엄청 친절한 open api 코인거래소 업비트 오픈 API로 실습해보겠다.

docs.upbit.com/reference#%EC%8B%9C%EC%84%B8-%EC%A2%85%EB%AA%A9-%EC%A1%B0%ED%9A%8C

 

업비트 개발자 센터

업비트 Open API 사용을 위한 개발 문서를 제공 합니다.업비트 Open API 사용하여 다양한 앱과 프로그램을 제작해보세요.

docs.upbit.com

이보다도 친절하고 멋진 API 센터가 있을까

 

 

 

우선 처음은 아래의 api url

https://api.upbit.com/v1/market/all

업비트에서 다루는 모둔 코인과 해당 코인모델코드명 JSON 리스트이다.

 

모듈은 import requests, 별도로 pip 설치 하지 않더라도

python3 이상에는 기본 내장되어 있는듯 하다

 

 

이렇게 해도 되고,

import requests
url = "https://api.upbit.com/v1/market/all"


response = requests.get(url)
print (response.json)

#실행결과 >>[{'market': 'KRW-BTC', 'korean_name': '비트코인', 'english_name': 'Bitcoin'}, {'market': 'KRW-ETH', 'korean_name': '이더리움', 'english_name': 'Ethereum'}, {'market': 'BTC-ETH', 'korean_name': '이더리움', 'english_name': 'Ethereum'}, {'market': 'BTC-LTC', 'korean_name': '라이트코인

 

이렇게 해도된다, 형태는 다르지만 결과는 똑같다 절차상 무슨 큰차이가 있는진 모르겠다.

header가 필요한 경우는 requests.request("GET", url, header="헤더값")이런식으로 넣을 수 있다. 

import requests
url = "https://api.upbit.com/v1/market/all"

response2 = requests.request("GET", url)
print (response2.json())

#실행결과 >>[{'market': 'KRW-BTC', 'korean_name': '비트코인', 'english_name': 'Bitcoin'}, {'market': 'KRW-ETH', 'korean_name': '이더리움', 'english_name': 'Ethereum'}, {'market': 'BTC-ETH', 'korean_name': '이더리움', 'english_name': 'Ethereum'}, {'market': 'BTC-LTC', 'korean_name': '라이트코인

 

그런데 사실 이 정도의 GET method 조회는 구글 크롬같은 브라우저에서 URL만 넣으면 그냥 나온다.

아래의 주소로 크롬에서 열면 위 결과값과 똑같이 페이지에 뿌려진다.

https://api.upbit.com/v1/market/all

 

그럼 python으로 request하면 장점은 무엇인가?

저 json 정보를 가져온 다음 원하는대로 파싱할수 있다는 것이다.

예를들어 json 두번째 항목인 '이더리움'정보만 보고 싶다면,

 

이렇게 print (response.josn[1])을 하면 (첫번째가 [0] 두번째가 [1]이다) 두번째 json그룹인 이더리움 정보만 나온다.

import requests
url = "https://api.upbit.com/v1/market/all"


response = requests.get(url)
print (response.json[1])

#실행결과>>{'market': 'KRW-ETH', 'korean_name': '이더리움', 'english_name': 'Ethereum'}

 

이더리움의 영어 명칭만 뽑아내고 싶다면?

이렇게 문자열 [1]로 들어간 depth에서 ['english_name']를 지정해주면 해당 value를 받을 수 있다.

json은 아주 심플한 key:value 형태로 ['key 명칭']만 넣어주면 짝지어진 value를 뽑을수 있다

import requests
url = "https://api.upbit.com/v1/market/all"


response = requests.get(url)
print (response.json[1]['engilish_name'])

#실행결과>> Ethereum

 

자 그러면 정말 중요한 실습예제다,

나는 업비트의 비트코인이나 이더리움 가격을 원하는대로 조회해 보고 싶다면 어떻게 해야할까,

우선 아래의 업비트 코인별 정보 ticker 현재가 조회 API URL을 사용한다

https://api.upbit.com/v1/ticker?markets="코인모델명"

자 그런데 'https://api.upbit.com/v1/ticker?markets=비트코인' 이런식으로는 값이 나오질 않는다. 404에러가 난다

docs.upbit.com/reference#%EC%8B%9C%EC%84%B8-ticker-%EC%A1%B0%ED%9A%8C

 

업비트 개발자 센터

업비트 Open API 사용을 위한 개발 문서를 제공 합니다.업비트 Open API 사용하여 다양한 앱과 프로그램을 제작해보세요.

docs.upbit.com

개발자 센터의 python 예제코드를 보면 알수 있듯이, 각 코인별 모델코드를 사용해야한다.

이게 바로 위에서 사용한 api.upbit.com/v1/market/all에서 나오는 모델코드명이다.

 

 

그러니 한글로 '비트코인', '이더리움', '라이트코인'만 넣어도 뚝딱 가격이 나오게 하고싶으면,

api.upbit.com/v1/market/all에서 한글명에 key로 매핑된 '모델코드명'으로 변환하여, markets 파라미터 값으로 넣으면된다.  

 

모델코드명으로 변환하려면 일단 api.upbit.com/v1/market/all에서 수집하여 새로운 {한글명:모델코드명} 형태의 dictionnary 포맷으로 만들어야 한다. 이건 다음 포스팅에서...

1. 타겟 문자열의 개수 세기,  (  ).count('찾는문자열)

 print("hobby".count('b)) => 2

혹은

a = "hobby"

print(a.count(''b)) = > 2

 

어디에 활용할지는 고민

 

2. 타겟 문자열의 위치 알려주기 (find)

sentence = "python is best choice"

print (sentence.find('best')) => 10 (0부터 시작)

 

3. 타겟 문자열의 위치 알려주기 (index)

sentence = "python is best choice"

print (sentence.index('best')) => 10 (0부터 시작)

 

find와 차이점은 거의 없지만,

find는 없는 문자를 찾으면 -1로 정상반환,

index는 에러를 발생시킨다. 뭐가 더 스탠다드일까?

 

4. 공백 지우기 (strip, lstrip. rstrip)

sentence = '   daniel  '

print (sentence.strip()) => 'daniel'  #양쪽 여백 지우기

print (sentence.lstrip()) ='daniel  '  #왼쪽 여백 지우기

print (sentence.rstrip()) =  '   daniel' #오른쪽 여백 지우기

 

양쪽 여백 지우기는 매우 자주할것 같다. 데이터 정규화에 필수

 

 

5. 대문자 소문자 바꾸기 (upper, lower)

sentence1 = 'you can do it'

sentence2 = 'You Can Do It'

 

print(sentence1.upper()) => "YOU CAN DO IT"

print(sentence2.lower()) => "you can do it"

 

6. 문자열 삽입 (join)

a.join('bbb') # 형태

 

a = '_x_'  #삽입할 문자열

'bbb' = #삽입될 문자열

print (a.join('bbb')) = b_x_b_x_b

 

그런데 join은 어디다 쓰는 경우가 있을까? 

스펠 단위로 문자열을 끼워넣는 경우가...

 

 

그리고 굉장이 자주 사용할수 밖에 없는 중요한 함수

 

7. 문자열 바꾸기 (replace)

sentence = 'life is good'

print ( sentence.replace('life', 'money') ) = >  money is good

 

8. 문자열 나누기 (split)

sentence = 'life is good'

print (sentence.split(' ')) => ['life', 'is', 'good'] list로 분리된다.

print (sentence.split(' ')[1]) =>  'is' (list중 두번째[1] 선택하기)

 

sentence = 'life is good'

splited = sentence.split(' ')

for word in splited:

 print (word)

 

=> life

     is

     good

 

for문으로 단어별 분리됨

 

 

 

 

 

 

 

 

 

 

 

 

나는 원래 문자열에 변수는 "문자열" + str(변수) 처리해 버리지만

별로 스탠다드한 방식은 아닌듯하다. 포매팅을 구성지게 사용해보자

 

(1)예제

print ("%d Completed" %99) => 99 Completed

 

(2)예제, %를 문자열로 표현하고싶으면 반드시 %%를 뒤에 붙여야함

percent = 56
print ("%d%% Completed" % percent)

 

 

[포맷코드]

%d = 정수 (퍼센티지 시에는 권장된다)

%s = 문자열 (모든값을 문자열로 치환가능)

%f = 부동소수

%c = 문자1개 character

 

[소수점 몇째자리까지 표혐]

부동소수 %f를 사용하며, 

"%0.0f"같은 형태로 표한한다.

0.부분은 자리 정렬공백쓰기, .0은 소수점 자리수를 의미한다

 

ex 1)
percent=94.1234
print("result: %0.2f%% Completed" %percent)>> result : 94.12% Completed

 

ex 2)

percent : 94.1234

print("%10.2f%% Completed" %percent) >> result:       94.12% Completed

 

 

 

(1) 인덱싱보다 유용한 케이스, 슬라이싱 (slicing)

 문자열의 특정범위만 추출

 a = Life is too short, You need python

 print(a[0:4])  = life

 print(a[19:]) = You need python (끝까지범위)

 

 마이너스 기호도 사용가능하다. 역순으로 추출 

 print(a[-6:]) = python

 print(a[19:-6]) = You need

 

 

 

 

 

 

 

 

 

(1)나눗셈 나머지 계산 반환 연산자 (%) 

 예제 : 7%3 = 1

 

(2) 나눗셈 후 소수점 아래자리를 버리는 // 연산자

 예제 : 7//4 = 1

 

 

(3) 문자열에 따옴표 포함시키기 중에 백슬래시 사용법(\)

따옴표 바로앞에 백슬래시 처리

 예제 : say = 'python\'s favorite food is perl'

 

 

(4) \n (문자열 개행)

 예제 python\'s favorite food \nis perl'

 (그외  \t (탭간격) \000 (null)

 

 

(5) 문자열 곱하기 기능 (잘 쓸진 모르겠다)

'python'*3 = pythonpythonpython

 

 

 

df.drop_duplicates(['열 명칭'])

 

엑셀 중복제거 처럼 특정 열을 지정하여, 데이터프레임 중복제거가 가능하다.

그런데 복수 열 중복제거 지정은 어떻게 하면 될까..?

df = pd.read_excel(expath, sheet_name="시트명")

 

참고로 엑셀은 csv등에 비해

로딩 시간이 길다.

 

+ Recent posts