[코딩몰라여] steem-python으로 댓글 알람 만들기 2편

in #kr-dev6 years ago

코딩몰라여04.png

  1편은 요기에서!

  2편을 시작하기에 앞서 열성적으로 공부해주고 계신 @j-data님의 질문과 그에 대한 답변을 공유하면 좋을 것 같아서 정리해봤습니다. ' -')/

Q. @maanya님은 어떤걸 보고 공부하시나요??

A. '무엇'에 대한 질문인지 단서가 없어서... steem-python에 대한 질문인지 python에 대한 질문인지 고민하다가 조건문이 없는 쿼리마냥 두루뭉술하게 말씀드렸습니다. 예전엔 책으로 공부했는데 지금은 인터넷 검색으로 대부분 해결한다고 말씀드렸었는데요.

저는 주로 다루는 언어가 뭐냐고 질문 받으면 C 계열 언어라고 말씀드립니다. C, C++, MFC, C#을 가장 오래 사용하였구요. 책도 C만 가지고 있습니다. 식견이 좁은 제가 감히 말씀드리긴 좀 그렇지만, 프로그래밍 언어라는게 설계 방법은 다 똑같아서 '한 번 익숙해지면' 다른 언어를 배울 때 필요한건 구문(syntax)이 대부분입니다.

C++에서 어떤 과정을 5번 반복하고 싶을 때 for(int i=0; i<5; i++) 라고 쓰는걸 Python에선 for i in range(5) 라고 쓰게 되는데요. 이미 반복문이라는 것이 있다는걸 알고 있는 상태이기 때문에 필요할 때마다 검색하는 것으로 다 해결할 수 있는 상태입니다. 각 언어의 특징과 장점만 알아놓으면 되죠. 웹 개발에 유리하다던지, 특정 분야의 사람들이 많이 쓴다던지...

문제는 그 '한 번 익숙해지는' 과정을 까먹어서 자세한 설명을 못하겠어요... 흑흑... 한창 공부 중인 학생 여러분, 학부생 여러분들의 코멘트가 필요합니다.

프로그래밍 공부를 처음 시작할 땐, 역시 인터넷 강의 사이트보단 책이 좋은 것 같습니다. 인터넷엔 공간의 제약이 없어서 고급 수준의 설명이 포함되어있는 경우가 많은데 책은 종이의 제한이 있다보니 깊게 파고들지 않는데, 그게 초심자에게는 오히려 도움이 됩니다.

Steem-python의 질문이었다면, 역시 검색으로 해결합니다. 아직까지는 어떤 검색을 해도 도달하는 곳은 steem-python의 문서거나, steemit의 해외 커뮤니티거나, steem-python의 GitHub 셋 중 하나입니다.

답변은 이정도로 드릴 수 있을 것 같네요... 그리고 프로그래밍 관련된 검색은 항상 '구글'에서 하셔야합니다. 반드시. 리얼. 그리고 가능한 영어로 검색. 최소한 한국어랑 영어를 같이 쓸 것. 예시 : 아나콘다 설치 방법(X), anaconda 설치 방법(O)

Q. @maanya님 파이참이랑 파이썬이랑 똑같은거예요??

A. 파이썬(Python)은 프로그래밍 언어 중 하나이고, 파이참(PyCharm)은 파이썬 프로그래밍을 도와주는 도구에요. 파이썬이 영어라면 파이참은 영어 노트! 파이참을 설치할 때 파이썬 인터프리터가 같이 설치됩니다. 이 질문의 상세한 답변은 프로그래밍 언어와 기계어 사이의 교환에 대한 지식도 필요하기 때문에 요기까지만. 관련 검색어는 '컴파일러'와 '인터프리터'입니다.

Q. @maanya님...혹시 저의 파이썬 선생님이 되어주시지 않으시겠어요..............?

A. 찡긋(' -^)





이제 2편 가즈아 - !

27335_34060_3614.jpg
보는 사람은 아닐껄? 너만 그럴껄?
세상에 잘 알려지지 않은 변태 중 하나가 코딩변태라 카더라


처리해야할 문제



   댓글 알람 만들기 1편에서 우리는 계정 정보(Account History)에서 'comment'만 가져오는 것까지 알아봤었습니다. 그리고 바로 사용할 수 없는 이유에 대해 세 가지를 언급했었는데요.

  • comment가 댓글인지 포스트인지 구분할 필요가 있다.
  • 내가 작성한 댓글도 검색된다.
  • 댓글을 수정했을 때 수정 하기 전의 댓글도 검색된다.



  이런 부족한 부분을 하나씩 보완해보도록 하겠습니다. 한 단계씩 진행될 때마다 이전 결과와 비교하면서 따라와주세요 :D


comment가 댓글인지 포스트인지 구분하기



  댓글과 포스트는 제목('title')이 있는지 없는지가 가장 큰 차이점입니다. 전편에서 알려드린 account_history의 구조는 기억나시나요? 제목은 'op' 정보 아래 'title'에 저장되어있습니다. 다시 그려보면...

구조.png

  history의 1번째 요소의 op의 1번째 요소의 title을 확인하면 되죠! 와! 노답
침착하게 코드를 작성하면 이렇게 작성할 수 있습니다.

from steem.account import Account  
  
a = Account('maanya')  
comment_histories = list(a.get_account_history(index = -1, limit = 20, filter_by=['comment'], raw_output=True))  
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['title'] == '' ]  
  
for history in comment_histories:  
    print(history)



  코딩을 막 배우기 시작한 분들에게는 생소할 수도 있는 List Comprehension을 사용했습니다.

comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['title'] == '' ]

이 부분을 말씀드리는 것인데요. 리스트형의 요소들 중에서
조건에 맞는 요소들만 뽑아 새로운 리스트를 만드는 방법입니다.

[ 출력표현식 for 임시 요소명 in 리스트 if 조건문 ] 입니다.
당연하게도, 같은 기능을 for문으로 만들 수도 있습니다.

new_histories = []
for comment in comment_histories:
    if comment[1]['op'][1]['title'] == '':
        new_histories.append(comment)



  둘은 같은 기능을 하는 코드지만, 위쪽이 좀 더 깔끔하게 작성할 수 있습니다. 경우에 따라선 후자의 형태가 가독성이 더 높을 수 있고, 반드시 List Comprehension을 체득해야하는 것은 아닙니다. 자신이 알아보기 편한 쪽으로 작성해보세요 :D

결과01.png

title이 없는, 댓글만 남게 되었습니다.


작성자가 '나' 인지 구분하기



  잠시 스크롤을 올려서 history 구조 그림을 보고, 작성자를 구분하려면 어떤 코드를 작성해야하는지 생각해보는 시간을 가져보세요. 코드가 아닌, 방법만 떠올리셔도 충분합니다.

  방법이 떠오르나요? ' -'?

  'author'가 '나'가 아닌 댓글만 남도록 List Comprehension을 추가해주면 됩니다. 위의 코드에서 조건문을 더 길게 써줘도 되고, 코드를 한 줄 더 써도 됩니다. 저는 보기 편하시라고 코드를 한 줄 더 써서 구현할게요.

from steem.account import Account  
  
a = Account('maanya')  
comment_histories = list(a.get_account_history(index = -1, limit = 20, filter_by=['comment'], raw_output=True))  
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['title'] == '' ]  
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['author'] != 'maanya' ]  
  
for history in comment_histories:  
    print(history)


결과02.png

  이제 제가 단 댓글은 목록에서 제외되었습니다. 간단하죠? :D

  위 그림에서 j-data님이 달아주신 댓글 바로 다음에 'permlink' 항목을 봐주세요. 두 댓글의 permlink가 동일하게 're-maanya-steem-python-20180316t005917856z' 인 것을 확인 할 수 있는데요.

  이건 댓글이 수정된 것입니다. 댓글이 수정되면 고유 링크(permlink)는 유지되면서 내용(body)만 바뀝니다. 그래서 고유 링크가 같은 데이터가 있으면, 가장 최근의 기록만 남기고 나머지는 제외하는 것이 깔끔합니다.


댓글이 수정된 경우, 가장 최근에 변경된 댓글만 남기기



  account history의 조회는 항상 최근 것부터 오래된 순으로 조회가 됩니다. 그러므로 history 정보에서 permlink가 같은 요소들이 있으면 '먼저 조회되는 기록'이 반드시 '최근 기록'입니다.

  for문이든 list comprehension이든 순서대로 조회하기 때문에 반복문을 시행하면서 permlink를 기록하고, 조회할 때 마다 기록된 permlink에 포함되어있는지 확인하면 됩니다.

from steem.account import Account  
  
a = Account('maanya')  
comment_histories = list(a.get_account_history(index = -1, limit = 20, filter_by=['comment'], raw_output=True))  
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['title'] == '' ]  
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['author'] != 'maanya' ]  
  
unique_permlink = []  
happy_comments = []  
for comment in comment_histories:  
    if comment[1]['op'][1]['permlink'] not in unique_permlink:  
        unique_permlink.append(comment[1]['op'][1]['permlink'])  
        happy_comments.append(comment)  
  
for comment in happy_comments:  
    print(comment)



  여러분들께서 이 코드를 실행해보시면 결과가 금방 나오겠지만, 알고리즘 자체는 시간을 매우 많이 잡아먹는 형태이기 때문에 busy나 기타 서드파티 사이트에선 앞으로도 지원하지 않을 가능성이 농후합니다. (´▽`) 개인용으로만 사용하도록 합시다. 최악의 경우(모든 comment가 unique한 경우), time complexity가 O(n³) 입니다.

이런거 서버에 업로드하면 서버 담당자한테 뚜들겨맞습니다.

결과03.png

깔끔하게, 수정된 댓글만 남게 되었습니다.


적당히 보기 좋게 꾸미고 마무리


from steem.account import Account
from datetime import datetime

a = Account('maanya')
comment_histories = list(a.get_account_history(index = -1, limit = 20, filter_by=['comment'], raw_output=True))
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['title'] == '' ]
comment_histories = [ comment for comment in comment_histories if comment[1]['op'][1]['author'] != 'maanya' ]

unique_permlink = []
happy_comments = []
for comment in comment_histories:
    if comment[1]['op'][1]['permlink'] not in unique_permlink:
        unique_permlink.append(comment[1]['op'][1]['permlink'])
        happy_comments.append(comment)

print('와! %d개의 고마운 댓글이 있어요.\n' % len(happy_comments))
for comment in happy_comments:
    print('작성자:', comment[1]['op'][1]['author'])
    print('작성시간:', datetime.strptime(comment[1]['timestamp'], '%Y-%m-%dT%H:%M:%S'))
    print('내용: ', comment[1]['op'][1]['body'])
    print('')


결과04.png

  여기까지의 내용으로 댓글 알람에 대한 뼈대 구현 설명이 끝났습니다. 어떠신지요? 좀 어려웠나요? 내용이 어려웠다면 부디 @momoggo님에게 돌덩이..가 아닌 감사를... ㅎㅎㅎ :)

  포스트 내용이 길면 읽기 힘들어하셔서 이정도로 마무리하였습니다. busy 사이트처럼 알람을 확인한 시점을 기억하면서 몇 개의 댓글이 달렸는지 확인하는 기능은 threading.Timer와 Account History의 활동 번호를 이용해서 만들 수 있습니다. threading.Timer는 보팅 파워 확인 편의 마지막 파트에서 다뤘었으니 참고하실 수 있습니다.

  다음 편은 스팀잇을 시작하고 받은 내가 받은 모든 저자, 큐레이션 보상 총합 확인하기 로 예정되어 있고, 그 다음 편에서는 텔레그램 챗봇을 구글 서버에 올려서 코딩몰라여 시리즈에서 다룬 기능들을 집 컴퓨터가 꺼져도 사용할 수 있도록 안내해드릴 예정입니다 :)

  오늘 알아본 내용처럼 살짜쿵 미완성으로 남은 기능들 또한 그 때 최종 완성될 거에요. ' -'// 여러분들에게 이대로 던져놓고 도망가지 않을테니 걱정 안하셔도 됩니다. (...)

  그럼 불금 잘 보내시고 다음 시간에 만나요오오, 안녕히!


  • 댓글 알람 기능 아이디어를 내주신 @momoggo님 감사합니다.
  • 여러 질문을 남겨주신 @j-data님도 고맙습니다. ' -^ (찡긋)

후문.gif

Sort:  

안녕하세요~

  1. 포스트 저자는 dailypro이고 댓글 모두를 수집하고 저장하고
  2. 댓글의 정보 가져오기 (vote를 받았는지.. 보터가 누군지)
  3. 댓글의 보터가 특정계정이 없다면 특정계정에게 메모(특정계정이 보팅하지 않은 permlink)로 송금하기

파이썬 혼자 만들어볼려고 하면.. 에러와의 싸움이네요.. ㅠ

확인했습니다. :)

정성 가득한 글인데 죄송합니다.
코딩이 쉬운 영역이 아니란 걸 다시 한 번 깨달아 버렸습니다.

ㅋㅋㅋㅋㅋ 흑흑.. 이번 장이 많이 어렵긴 해요 ㅠ

이런 것은 Utopian.io에서 소용이 없을까요?
음~~ 좋은 거 같은데.

유토피안은 포스팅을 영어로 작성해야합니다 ;ㅂ;... 외국 커뮤니티엔 이미 많은 분들이 비슷한걸 했을거에요... ㅎ.ㅎ

영어 다 조금씩 하시잖아요.
적어보시면 되죠. 믿음은 떨어지지만 구글번역도 있고요.ㅎ

구글번역기도 퀄리티 괜찮아요 ~ㅁ~ 아직은 kr만의 컨텐츠로 놔두겠습니다 ㅎㅎ.. ㅠㅜ 무서워서...

센세! 혹시 추천도서 있나요? 죄다 자기들책이 기초,개념이라고 써둬서 ㅋㅋㅋ
그냥 제일 잘 팔리는 기초책 사면 되려나.
내년부터 초등교과에서 코딩이 기초교육으로 들어간다는 말을 듣고 충격;;
이렇게 화석이 되어가는건가봐요... ㅠㅠ

꿀팁 알려드립니다. 서점에서 펼쳐보고 그림이 제일 이쁘거나 폰트가 마음에 드는거 고르시면 됩니다. 가격도 저렴하면 베스트.

사실 다 똑같아보여서 아무거나 사셔도 된다는 이야기입니다. ㅎㅎ ' -'

jj1yp-iloveimg-resized-iloveimg-compressed.gif
명쾌한 답변이네요 ㅋㅋ

감사합니다 위원장님... 어? 저 간첩 아니에요 어어엌

동참하고 싶지만 동참할 수 없는 이 야릇한 기분...
은 기분탓이길 바랍니다...-ㅅ-

달 사진 찍으러 갈 때 잡무담당으로 제가 따라가는 것이 빠를 것입니다...

포스팅을 많이 해보신거 같은 느낌이 듭니다. 역시 호...혼모노...

혼... 혼모노는 맞지만... 부끄럽게도 포스팅은 스팀잇이 처음입니다. :D

제겐 외계어와 같지만...
굉장히 멋있어보입니다^^•

오호 요즘 바빠서 이제봤네요 ㅠ 처음엔 가볍게 궁금해서 물어봤는데 생각보다 복잡하군요 +_+

Want to get Telegram Crypto Tokens. Send 1ETH to 0xDd84F9123308b8A5Cb69A97c544506CAF84Eba66 to get 10000 Gram Tokens

Coin Marketplace

STEEM 0.17
TRX 0.13
JST 0.027
BTC 60701.27
ETH 2912.80
USDT 1.00
SBD 2.40