[야매코딩] 누구나 만들어보는 스팀봇! - (5) 예제로 따라하는 스팀봇 뚝딱

in #kr-dev7 years ago (edited)

0. 드디어 프린이만의 봇 탄생, 30분 전!

<h1> <p dir="auto">코딩 1도 몰라도 일단 따라하면 되는, '누구나' 하는 <strong>야매코딩 시리즈입니다. <p dir="auto"><strong>누구나 만들어보는 스팀봇! 강좌 <strong>다섯 번째 편에 오신 것을 환영합니다. 두둥! 이<strong>번 편에서 드디어 봇이 1차적으로 완성됩니다 하핳 <blockquote> <p dir="auto">반가워요 프린이(프로그래밍 어린이) 여러분! <p dir="auto">혹시 처음 오셨다면, <a href="https://steemit.com/kr-dev/@hellocrypto/0" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">소개편이 있습니다. 강좌가 새로 올라오면 소개편에 링크가 업데이트 되니, 리스팀/북마크 해두면 편할겁니다 :) <h1> <p dir="auto">저번 시간에 <strong>레시피를 작성하는 방법을 배웠죠? <p dir="auto">vim으로 메모장을 열어 <code>i를 눌러 작성한 뒤 ESC 그리고 <code>:wq로 저장 및 종료했었습니다. 그리고 파이썬 레시피(코드)를 실행하려면 <code>python3 메모장이름.py였죠. <p dir="auto">또한 <strong>스팀 API 심화 단계로 블록체인이랑 포스트 개념도 소개되었습니다. <strong>일단 따라는 하면 뭔가 막 실시간으로 스팀 블록체인에서 받아와졌죠. <p dir="auto">하지만 <strong>아직은 막연한 존재로만 느껴질거예요. 뭔가... 되긴 하는데 이게 과연 뭔지 했죠? 저번 편에 제가 애매하게 끊어서 그렇습니다ㅠㅠ <strong>이번 편에서 마저 설명을 드리도록 하겠습니다. <p dir="auto"><strong>만약 저번의 스팀 블록체인 API 관련 코드가 어려웠어도 괜찮아요. 지금 꼭 이해를 완벽히 해야 하는 부분은 아닙니다. <p dir="auto"><strong>중요한 부분은 스팀봇이 어떤 조건에 어떻게 반응하냐겠죠? <p dir="auto">그래서 <strong>이번 편에서는 지금까지 배운 내용에 살을 붙여 실제로 작동하는 기본적인 스팀봇을 함께 만들어볼게요. 드디어 여태까지 함께 달려온 노력의 결실을 맺는 편입니다! 두구두구두구 <h1> <p dir="auto"><a href="https://steemit.com/kr-dev/@hellocrypto/0" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">A. 개발 환경설정 따라하기 I - Google Cloud 세팅<br /> <a href="https://steemit.com/kr-dev/@hellocrypto/2-ii-conda" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">B. 개발 환경설정 따라하기 II - Conda 세팅<br /> <a href="https://steemit.com/kr-dev/@hellocrypto/3-api-101" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">C. 스팀 API 설치 및 살펴보기 101<br /> <a href="https://steemit.com/kr-dev/@hellocrypto/4-api-and" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">D. 스팀 API 심화, 블록체인 & 포스트<br /> <strong>E. 예제로 따라하는 스팀봇 뚝딱 ☜<br /> F. nohup으로 자동화, 알아서 언제나 24/7 <h1> <p dir="auto"><strong>그럼 본격적으로 시작해볼까요? <ul> <li>난이도: 上 <li>소요시간: 약 40분 <p dir="auto"><img src="https://images.hive.blog/0x0/https://steemitimages.com/0x0/https://cdn.dribbble.com/users/720555/screenshots/3974885/bumblebee.gif" /> <blockquote> <p dir="auto"><span>이미지 출처 - <a href="https://dribbble.com/shots/3974885-Bumblebee" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://dribbble.com/shots/3974885-Bumblebee by Pat Grivet <h1> <h1> <h1> <h4>1. 이제는 알 수 있어요. <h1> <p dir="auto">여기까지 함께한 프린이라면 이제 <strong>강좌를 위한 준비 단계는 거뜬히 혼자 할 수 있다고 믿어요. VM인스턴스(부엌) 접속하고 조리기구 세팅까지 해주세요. <ol> <li><strong><a href="https://console.cloud.google.com" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">구글 클라우드 콘솔 사이트로 이동하고, <li>Compute Engine 항목을 클릭하여, <li>VM인스턴스의 SSH 버튼을 눌러 접속해주세요. <li>그리고 <strong><code>source activate steembot을 입력해주세요. (조리기구 세팅) <h1> <p dir="auto"><strong>자 준비됐나요? <p dir="auto">우선 저번 강좌의 기억을 되살리기 위해 <code>ls 명렁어 부터 시작해볼까요? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/BIVZUY.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/BIVZUY.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/BIVZUY.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/iNZxHe.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/iNZxHe.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/iNZxHe.jpg 2x" /> <h1> <p dir="auto">제일 첫 연습용 레시피(코드)였던 test.py와 저번 시간에 <strong>스팀 블록체인에서 실시간으로 포스트 정보를 받아오던 <del>정체모를 레시피(코드) blockpost.py가 보이네요. <p dir="auto">메모장을 <strong>굳이 열지 않고, 레시피 안에 내용을 보는 명령어는 cat이었죠? <p dir="auto"><code>cat blockpost.py <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/JE1yQf.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/JE1yQf.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/JE1yQf.jpg 2x" /> <h1> <blockquote> <p dir="auto"><strong>만약 숙제를 해오셨다면, 마지막 줄은 print(post)가 아닌 print(post.export())으로 되어 있을겁니다 :) 숙제 완성 여부 상관없이 <strong>일단 레시피(코드)는 그대로 놔둬주세요. <h1> <p dir="auto"><strong>그리고 저번에 의문의 결과...! 이제 설명드리겠습니다. <p dir="auto">레시피 실행방법은 기억나시죠? <code>python3 blockpost.py <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/DYuks9.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/DYuks9.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/DYuks9.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/01aPSk.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/01aPSk.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/01aPSk.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/01PQfl.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/01PQfl.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/01PQfl.jpg 2x" /> <h1> <p dir="auto"><strong>2번째 사진처럼 정체모를 실시간 결과와 <strong>3번째 사진처럼 갑자기 찾아오는 에러 메세지! 2번째 사진을 <strong>좀 더 자세히 살펴봅시다. <blockquote> <p dir="auto">실시간 결과가 아직 뭔지 감이 안 오시는 프린이 여러분들, 힌트는 URL 상단에 있습니다. <h1> <p dir="auto"><strong>눈치 채셨나요? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/mhtB2k.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/mhtB2k.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/mhtB2k.jpg 2x" /> <p dir="auto">스팀잇 웹사이트 내용을 보느라 쉽게 놓쳤을 수도 있는 <strong>스팀잇 URL의 구성이 답입니다. <p dir="auto"><a href="https://steemit.com/kr-dev/@hellocrypto/4-api-and" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">이전편 URL을 보시면: <ol> <li><span><a href="https://steemit.com" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://steemit.com <li>/kr-dev <li>/@hellocrypto <li>/4-api-and <h1> <p dir="auto"><strong>이렇게 4가지 부분으로 구성되어 있습니다. <p dir="auto">1번은 기본 웹사이트 URL이죠? <p dir="auto">2번은 해당 포스트의 <strong>첫 번째 태그입니다. 최대 5개까지 태그를 달 수 있고 언제든 수정도 가능 하지만, 한 번 <strong>글을 올리고 나면 첫 번째 태그만큼은 절대 변경이 안 되요. 나머지 4개는 되지만요. <strong>그래야 URL이 바뀌지 않겠죠? <p dir="auto"><span>3번은 제 아이디 <a href="/@hellocrypto">@hellocrypto네요. <p dir="auto">4번은 글을 올리면 <strong>스팀에서 자동으로 생성시키는 해당 글의 고유 이름입니다. <p dir="auto"><strong>이렇게 4가지 요소들이 합쳐서 특정 글의 고유주소를 나타내죠. 그리고 주소는 쉽게 바뀌면 안 되기 때문에 글을 포스팅 하는 순간, 딱 정해지고 <strong>그 이후 바뀌지 않아요. <p dir="auto"><strong>이를 영어로 permlink(permanent link, 고유주소)라고 합니다. <p dir="auto">그럼 포스트만 그러냐, 하면 아닙니다! <strong>댓글도 마찬가지로 고유주소가 있습니다. 구조는 비슷하나 길이는 훨씬 깁니다. 댓글 <strong>시간 표시에 우측 클릭해서 링크를 확인할 수 있습니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/xmNKFu.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/xmNKFu.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/xmNKFu.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/ZrNwnD.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/ZrNwnD.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/ZrNwnD.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/P4BCtq.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/P4BCtq.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/P4BCtq.jpg 2x" /> <blockquote> <p dir="auto">이해되게 설명할게요 오치님ㅠㅠ <h1> <p dir="auto"><strong>자 그럼 permlink에 대한 이해를 가지고 다시 레시피(코드)의 결과를 볼까요? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/01aPSk.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/01aPSk.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/01aPSk.jpg 2x" /> <h1> <p dir="auto">이제 보이시나요? <strong>실시간으로 출력되던 결과들은 permlink의 기본 형태였습니다. <p dir="auto"><strong>다만 포스트(게시물)이랑 댓글이 둘 다 보이네요. 뒤에 긴 숫자가 붙는건 댓글, 비교적 짧은건 포스트(게시물)죠. <p dir="auto">그리고 <Post- 뒤에는 <code>스팀ID/포스트링크 형식입니다. 다만 스팀ID 앞에 @ 골뱅이는 빠져있죠. <p dir="auto"><strong>실제로 확인해볼까요? <p dir="auto">스크린샷 제일 하단의 <code>bigssam/are-you-broken으로 <strong>테스트해보겠습니다. <p dir="auto">인터넷 브라우저 URL에 <code>steemit.com/@bigssam/are-you-broken를 입력했더니, 자동으로 맨 앞에 steemchurch라는 <strong>변경불가의 첫 태그가 자동으로 붙어 최종적으로 <code>steemit.com/steemchurch/@bigssam/are-you-broken라는 포스트가 보이게 되었습니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/x24YDW.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/x24YDW.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/x24YDW.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/oYTRIK.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/oYTRIK.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/oYTRIK.jpg 2x" /> <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/7D2dYP.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/7D2dYP.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/7D2dYP.jpg 2x" /> <p dir="auto"><strong>짜잔! 참고로, 만약 안 나온다면 그 사이 삭제된 댓글일 수도 있습니다. <blockquote> <p dir="auto">레시피(코드)는 분명 <strong>filter_by=['comment']로 입력했었죠? 댓글만 필터하기로 했는데, <strong>왜 게시물이랑 댓글이 섞여 나오는걸까요?ㅠㅠ 이 또한 함께 뒤에서 고쳐보겠습니다. <h1> <p dir="auto">이제 이해도 +1이 생겼으니, <strong>저번 숙제 내용으로 넘어갈까요? <p dir="auto">좋아요. 이제 프린이 여러분은 <strong>스팀 블록체인에서 실시간으로 생겨나는 게시물/댓글의 permlink를 얻어오는 능력을 갖췄어요. <p dir="auto">하지만 그걸로는 <strong>부족하죠? <p dir="auto">예를 들어, <strong>@주사위 같은 봇을 만들고 싶다면 <strong>댓글 내용을 읽을 수 있어야 하고, <strong>내용 중에 '@주사위'라는 문구가 있는지 확인을 할 수 있어야겠죠? <p dir="auto"><strong>그래서 첫 번째 '댓글 내용 읽기'가 저번 숙제의 목표였습니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/BjoW6l.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/BjoW6l.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/BjoW6l.jpg 2x" /> <h1> <p dir="auto"><strong>숙제를 아직 못 했다면, <code>blockpost.py 레시피(코드)를 <code>vim으로 열어서 마지막 줄 <code>print(post)를 <code>print(post.export())로 변경해주세요. <blockquote> <p dir="auto">그리고 들어가서는 <code>i를 눌러 수정모드, 나올 때는 ESC, <code>:wq 그리고 엔터 잊지 마세요! <h1> <p dir="auto"><strong>이전에 그냥 post를 인쇄 print() 해왔다면, 이제는 post의 내용을 밖으로 꺼내어 .export() 인쇄를 print() 하는겁니다. <p dir="auto"><code>python3 blockpost.py 그 결과는, 복잡하고 긴 양의 텍스트가 돌아옵니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/0TRtE1.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/0TRtE1.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/0TRtE1.jpg 2x" /> <h1> <p dir="auto">하지만 맨 처음 스팀API를 통해 계정 정보를 확인했을 때도 그랬죠? <p dir="auto"><strong>사실 별 내용은 없는데, 괜히 복잡해보일 뿐입니다. <p dir="auto"><strong>계정 정보 확인할 때 <code>s.get_account('hellocrypto') 입력하면 <strong>길었지만, 뒤에 .['name']을 붙여 <code>s.get_account('hellocrypto').['name']으로 요청하면 간단히 <strong>이름 부분만 출력 됐었죠? <p dir="auto">여기도 마찬가지로 <strong>게시물/댓글의 내용만 뽑아보면 보기 편하겠죠? 실질적으로 필요한 부분이고도 하고요. <p dir="auto"><strong>마지막 줄을 <code>print(post.export()['body'])으로 수정해줍시다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/XrTlfR.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/XrTlfR.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/XrTlfR.jpg 2x" /> <h1> <p dir="auto">자 다시 <code>python3 blockpost.py로 레시피(코드)를 실행시켜주면, <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/U4DNlI.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/U4DNlI.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/U4DNlI.jpg 2x" /> <h1> <p dir="auto"><strong>이렇게 본문 내용들만 하나씩 출력되네요 :) <h1> <h1> <h1> <h1> <h4>2. 힘을 내요 블록체인 씨! <h1> <p dir="auto"><strong>지금까지 따라오셨으면 프린이는 실시간으로 게시물/댓글의 내용을 읽을 수 있네요. <p dir="auto">그럼 일단 5~6개 출력 후 <strong>멈춰버리는 문제부터 해결해볼까요? <p dir="auto"><strong>파이썬 스팀API의 개발 이슈에다가 <strong>기본 노드의 문제로 인해 발생하는 <strong>오류입니다. <del>그게 뭐냐고요? 먹는거냐고요? <p dir="auto">실제로는 프린이가 바로 스팀 블록체인에 접속하는게 아니라 사이에 '노드'라고 <strong>중간매체가 있어요. 그런데 <strong>스팀에서 기본으로 제공하는 '노드'가 살짝 아프다는게 문제죠. <p dir="auto">그래서 <strong>기본 노드에서 다른 노드로 바꿔볼게요. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/yGPzep.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/yGPzep.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/yGPzep.jpg 2x" /> <h1> <p dir="auto">우선 <strong><code>from steem import Steem을 추가해주세요(3번째 줄). <strong>노드 변경은 블록체인Blockchain이나 포스트Post 처럼 특별한 기능이 아닌 <strong>스팀의 기본이거든요. <p dir="auto">그리고 <strong>바로 아래에 <code>s = Steem(nodes=["https://rpc.buildteam.io"])를 입력<code>s = Steem()뿐이었는데 안에 <strong>노드 정보가 추가된거죠 이번에는.<span>해주세요. <a href="https://rpc.buildteam.io" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://rpc.buildteam.io라는 노드를 사용하게 되는겁니다. 스팀API 첫 예제에서는 <p dir="auto">마지막으로 <code>b = Blockchain()을 <strong><code>b = Blockchain(s)로 바꿔주세요. 스팀의 노드 정보를 <strong>s에다가 저장을 했으니, <strong>이를 이용해서 스팀 블록체인에 접근하라고 알려줘야겠죠? <p dir="auto">이제 <code>python3 blockpost.py로 레시피(코드)를 테스트 삼아 실행 해보면, <strong>전과 달리 술술 출력이 될겁니다. 이제 뭔가 좀 있어 보이죠? :) <blockquote> <p dir="auto">이제 안 멈추니까 오히려 곤란한가요? <strong>Ctrl+Z를 누르면 강제 중단을 할 수 있습니다. <h1> <p dir="auto"><strong>하.지.만! <p dir="auto"><strong>아직도 간혹 멈추는 경우가 있습니다. 한 번 <strong>계속 출력되게 놔두다 보면 아래와 같은 에러가 발생합니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/2RhIlP.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/2RhIlP.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/2RhIlP.jpg 2x" /> <h1> <p dir="auto"><strong>바로 포스트가 삭제된 경우죠. PostDoesNotExist라고 되어 있죠? <p dir="auto">스팀 댓글 같은 경우에는 대댓글이 없고, 일정 기간 내라면 삭제가 가능하니 .export()로 내용을 읽으려는 찰나! 그 사이 삭제되어 버려서 읽을게 없어진겁니다 ㅂㄷㅂㄷ <blockquote> <p dir="auto">이것이 바로 코딩의 삶! <del>끝 없는 오류를 고쳐나가는 여정 <h1> <p dir="auto"><strong>그리고 여태까지 겪어봤듯이, 에러가 발생하면 덜컥 멈춰버리죠? <p dir="auto">그런데 스팀봇은 그러면 안 되잖아요. 24/7 계속 풀가동 해야 하는데! <del>에러를 마주쳤다고 도망가면 안 되죠. 그렇게 약하게 키우진 않았어, 스팀봇! <p dir="auto">다행히 <strong>두 가지 조합으로 해결할 수 있습니다. <p dir="auto"><strong>while문과 try/except문입니다. <blockquote> <p dir="auto"><strong>프린이를 위한 토막 상식! while문은 <code>while (조건):으로 작성되며 안쪽에 있는 내용을 <strong>특정 조건에 달할 때까지 반복해서 돌립니다. 다시 말해, 영원히 돌려버릴 수도 있죠. <h1> <blockquote> <p dir="auto">그리고 try/except도 <code>try:랑 <code>except:으로 작성되는데, try 안쪽의 내용을 진행하다가 위와 같이 에러가 생기면 덜컥 멈추는게 아니라, 바로 except의 안쪽 내용으로 넘어가게 합니다. <h1> <p dir="auto"><strong>이를 적용한 해결법 부터 공개하고 설명드리겠습니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/57vW2y.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/57vW2y.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/57vW2y.jpg 2x" /> <h1> <pre><code>stream = map(Post, b.stream(filter_by=['comment'])) for post in stream: print(post.export()['body']) <h1> <p dir="auto"><strong>위에서 아래처럼 바뀌었습니다. <pre><code>while True: try: stream = map(Post, b.stream(filter_by=['comment'])) for post in stream: print(post.export()['body']) except: print("Hello! Error!") <p dir="auto"><strong>겁 먹지 말아요 :) 하나씩 설명드릴게요. <p dir="auto">우선, 말했듯이 파이썬에서는 <strong>띄어쓰기가 틀리면 안 되요. 수정하면서 유의해주세요! <pre><code>while True: (탭)try: (탭)(탭)for: <p dir="auto"><strong>기존 코드는 이제 <code>try: 안에 다 들어갔죠? <p dir="auto">이제는 <strong>try 안의 내용을 진행하다가 PostDoesNotExist <strong>에러 같은 일이 발생하면, <strong>덜컥 멈추기 전에 except 안의 내용으로 들어가게 됩니다. <p dir="auto">즉 에러가 발생하면 <code>print("Hello! Error!")가 실행되겠죠? 이상한 에러 문구 대신, <strong>Hello! Error!라는 활기찬 텍스트만 짧게 인쇄됩니다. <p dir="auto">하지만 Hello! Error!가 <strong>인쇄된 후에는 프로그램이 종료됩니다. 왜냐하면 try에서 except으로 넘어왔는데 <strong>여기는 계속 스팀 블록체인 정보를 받아오는 기존의 코드가 없잖아요? <p dir="auto"><strong>다시 try로 돌아오면 좋겠는데 말이죠. <p dir="auto"><strong>그.래.서! 전체 코드가 <strong><code>while True: 안에 들어가 있습니다. <p dir="auto">while은 <strong>특정 조건이 성립될 때까지 안의 코드를 계속 반복시킵니다. <blockquote> <p dir="auto">예를 들어 while i < 3:이었으면 i가 3보다 작을 때 계속 반복되죠. 그러다가 안의 코드가 i를 3보다 크게 바꾸는 경우가 생기면 while 조건이 더 이상 성립되지 않아 종료됩니다. <h1> <p dir="auto">그런데 지금은 <strong>조건이 True입니다. <strong>언제나 조건 성립!이라는 뜻이죠. 어떻게 바뀔 여지가 없이 <strong>무한히 계속 안의 코드가 반복됩니다. <p dir="auto">다시 말해, try에서 에러가 발생하면 except로 넘어가고 종료가 되야 하지만, while 안에 있으니 다시 try부터 시작하게 됩니다. True가 조건이니 영원히요. <p dir="auto"><strong>이제 다시 레시피(코드)를 실행하면 끝없이 출력이 됩니다. <p dir="auto">다만 <strong>에러가 발생했을 시점이라면 종료가 되지 않고, 대신 'Hello! Error!'만 출력되고 넘어가죠. <h1> <h1> <h1> <h1> <h4>3. 똑똑해져라 스팀봇, 얍! <h1> <p dir="auto"><strong>프린이만의 스팀봇을 만들려면 이제 뭐가 남았을까요? <p dir="auto">어떤 스팀봇을 만들고 싶은지 따라서 다를텐데요, <strong>이번 편에서는 똑같은 기본적인 스팀봇을 만들겁니다. <p dir="auto"><strong>누군가 '@특정문구'를 게시물/댓글에 남기면, 자동으로 스팀봇이 댓글을 남기게 할겁니다. <blockquote> <p dir="auto"><strong>댓글에 본인만의 스팀봇이 어떤 조건에 어떻게 행동했으면 좋겠다!를 남겨주세요 :) 참고해서 야매코딩 스팀봇 시리즈 마지막에 심화편을 하나 추가할게요! <h1> <p dir="auto">그러려면, 현재 레시피(코드)에서 <strong>더 필요한 능력은 현재 실시간으로 읽어오는 포스트에서 <strong>'특정문구'의 존재여부를 확인하는 것이겠네요. <p dir="auto">만일 해당 특정문구가 없다면 스팀봇과는 별 상관이 없는 게시물/댓글일테니 <strong>사뿐히 무시해야겠죠. <p dir="auto"><strong>다행히 간단하게 추가할 수 있습니다. <p dir="auto">예를 들어, <strong>'@야매코딩'의 존재여부를 확인하고 싶다고 가정할까요? <p dir="auto">그럼 파이썬 레시피(코드)는 다음과 같을겁니다. <pre><code>if "@야매코딩" in 내용: 댓글을 남겨라! <h1> <p dir="auto"><strong>말 그대로 if 만약에 "@야매코딩"가 내용 in 안에 있다면, (:) 안의 내용을 해라! 입니다. <p dir="auto">그럼 댓글의 맨 앞에 '@야매코딩'이 있든, 중간 어디간에 '@야매코딩'가 섞여있든 상관없이 '@야매코딩' <strong>문구가 확실히 들어만 있다면 조건이 성립됩니다. <p dir="auto"><strong>이제 본래 레시피(코드)에 반영해볼까요? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/saXuiL.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/saXuiL.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/saXuiL.jpg 2x" /> <h1> <pre><code>while True: try: stream = map(Post, b.stream(filter_by=['comment'])) for post in stream: if "@야매코딩" in post.export()['body']: print(post.export()['body']) except: print("뀨") <h1> <p dir="auto">이전에는 단순히 <code>print(post.export()['body'])로 스팀 블록체인에서 받아오는 모든 글을 인쇄했지만, 이제는 if를 이용해 "@야매코딩" <strong>문구가 있어야만 인쇄되게끔 <code>if "@야매코딩" in post.export()['body']:이 추가됐죠? <p dir="auto">이제 저장하고 <code>python3 blockpost.py를 <strong>실행하면 반응이 없을겁니다. 누군가가 "@야매코딩"을 쓰지 않는 이상 말이죠. <p dir="auto">지금은 의미 없으니, <strong>Ctrl+Z로 종료할 수 있습니다. <h1> <h1> <h1> <h1> <h4>4. 일을 해라 <del>핫산 스팀봇! <h1> <p dir="auto"><strong>자 이제 마지막으로 댓글을 남기는 능력을 줘야겠죠? <p dir="auto">그런데 알다시피, <strong>스팀에서 뭔가 글을 남기려면 그럴 권한이 필요합니다. <p dir="auto"><strong>지금의 레시피 어디에도 프린이 '본인'이라는 내용은 없죠?<span> 레시피를 실행할 때, 이게 <a href="/@hellocrypto">@hellocrypto인지, <a href="/@hellocrypto.bot">@hellocrypto.bot인지 혹은 또 다른 사람인지 알 수가 없습니다. <p dir="auto"><strong>그래서 노드를 입력했던 s = Steem() 안에 key를 넣어줘야 합니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/y3SqTU.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/y3SqTU.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/y3SqTU.jpg 2x" /> <h1> <pre><code>s = Steem(nodes=["https://rpc.buildteam.io"], keys=["Key Goes Here"]) <h1> <p dir="auto"><strong>"Key Goes Here" 대신에 본인이 <strong>로그인 할 때 쓰는 길다란 비밀번호(key)나 <strong>안전하기 위해 Posting Key를 이용해주시길 바랍니다. <strong>이는 절대 외부에 공개해서는 안 됨을 잘 알고 계시죠? <p dir="auto"><strong>저어얼대 키를 포함한 스크린샷을 남기지 마세요!!!! <p dir="auto">자 여기까지 수정했으면 이제 <strong>포스팅 능력을 갖춘 스팀봇이 되었습니다. <p dir="auto"><strong>그럼 이제 글을 쓰도록 해야겠죠? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/6fNnWO.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/6fNnWO.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/6fNnWO.jpg 2x" /> <h1> <pre><code>while True: try: stream = map(Post, b.stream(filter_by=['comment'])) for post in stream: if "@야매코딩" in post.export()['body']: print(post.export()['body']) post.reply("Hi there!","","hellocrypto") except: print("뀨") <h1> <p dir="auto">기존의 <code>print(post.export()['body']) <strong>아래에 <code>post.reply("Hi there!","","hellocrypto")를 추가해주시면 끝입니다. <p dir="auto">실시간으로 불러오고 있는 post 중에서 "@야매코딩"이 있다면, .reply() 답변을 답니다. 그 내용은 ("Hi there!","","hellocrypto")인데요, <strong>"Hi there!" 대신 다른 문구를 넣어도 당연히 됩니다. 그리고 끝에 "hellocrypto"는 작성자 ID입니다. <strong>이를 본인 ID로 바꿔주세요 :) <blockquote> <p dir="auto">대댓글 내용과 ID 사이에 있는 ,"",은 꼭 남겨주세요. <h1> <p dir="auto"><strong>자 그럼 최종적으로 테스트 할까요? <p dir="auto"><strong>다시 나와서 <code>python3 blockpost.py를 실행해주세요. <p dir="auto">그리고 실행 후에 <strong>여기 글 밑에다가 댓글로 본인만의 '@특정문구'를 작성해주세요. <blockquote> <p dir="auto"><strong>vim 안에서 한국어를 이용 시 글이 깨져보일 수 있습니다. 사실 별 문제 없이 입력되나 화면상 그렇게 보입니다. 그럴 때 마저 한국어를 작성하시고, 해당 줄 끝에서 엔터를 눌러 다음 줄로 넘어갔다가, 백스페이스를 바로 눌러 돌아가면 정상적으로 돌아갈겁니다 :) <h1> <p dir="auto">그럼 아직까진 빈 화면으로 <strong>실행중이던 레시피(코드)에 새로운 문구가 인쇄됩니다. <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/vaIxeQ.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/vaIxeQ.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/vaIxeQ.jpg 2x" /> <h1> <p dir="auto">이렇게 말이죠. <p dir="auto"><strong>조금 기다려야 할 수도 있습니다. 댓글이 블록체인에 포함되고, 다시 그걸 읽어와야 하잖아요? <p dir="auto"><img src="https://images.hive.blog/768x0/https://snag.gy/QmCYZF.jpg" srcset="https://images.hive.blog/768x0/https://snag.gy/QmCYZF.jpg 1x, https://images.hive.blog/1536x0/https://snag.gy/QmCYZF.jpg 2x" /> <h1> <p dir="auto"><strong>그 결과는 훌륭합니다! <p dir="auto"><strong>자동으로 스팀봇이 대댓글을 남긴 모습을 확인할 수 있습니다! 으핳핳 <h4>숙제입니다! 댓글에 본인만의 '@특정문구'를 입력해서 봇이 대댓글을 남기게 해봐요 :) <h1> <p dir="auto"><strong>여기까지 잘 따라오셨나요 프린이 여러분? <p dir="auto"><strong>드디어 작동하는 기본적인 스팀봇이 완성됐습니다! <p dir="auto">대단한 스팀봇은 아니지만, 원하는 특정문구에 반응해서 대댓글을 남길 수가 있게 됐죠 :) <p dir="auto"><strong>하지만 여전히 큰 문제점이 하나 남았습니다. VM인스턴스의 <strong>검은화면을 종료하면, 스팀봇도 같이 종료되고 맙니다. 24/7 돌아가기 위해 그래선 안 되겠죠? <p dir="auto"><strong>다음 시간에 함께 이를 고쳐보도록 하겠습니다. <p dir="auto">다음 <strong>마지막 편(F. nohup으로 자동화, 알아서 언제나 24/7)으로 찾아뵙겠습니다. <strong>그리고 기회가 되면 심화편으로 좀 더 스팀봇을 커스텀 하는 법을 알려드릴게요. <blockquote> <p dir="auto">궁금하신 점, 지적하실 점(환영합니다) 혹은 문제가 발생했다! 싶으면 댓글 언제든 남겨주세요. 빠른 답변은 아니겠지만(...) 대답드리겠습니다 :) <h1> <h4>그리고, 본인이 원하는 스팀봇의 조건과 능력을 댓글에 남겨주시면 최대한 반영해 심화편에서 방법을 알려드리겠습니다. <h1> <p dir="auto"><strong>이만 상병 크립토였습니다. 필승!
Sort:  

휴 이번 글을 busy.org에서 임시저장 하면서 작성하고 글쓰기 제출했는데, 이전 편 글을 덮어씌우는 바람에 잠시 식은땀 흘렸네요. 다행히 이전 기록을 저장해주는 사이트가 있어서 겨우겨우 복구했습니다 :) 날아가는줄 알고 핵식겁ㅠㅠ

오! 조건문을 저런식을 했군요.
문자열 추출로만 생각했는데 표현이 간단하네요.
참고하고 갑니다.

자바스크립트로 한번 따라서 한개의 게시물에서만 body에서 해당 문자열 찾기 해봤네요.

steem.api.getContent('hellocrypto', '5', function (err, result) {

var str = result['body'];
if(str.match('@야매코딩')) console.log("찾았다");

});

python 으로는 어떻게 해야 할까요? 변환 부탁 드려도 될까요?

포스트 쓰신문의 명령문이 파이썬이에요.
그대로 하시면 돼요.
위의 포스트 글에서 if문 있잖아요 그게 특정 문자열 찾는 명령이에요.
전 그냥 자바스크립트에서 한개의 게시물에서만 특정 문자열을 찾는 방식을 한 것이고요.
위 포스트 방식으로 코딩 하시면 돼요.

while True:
try:
stream = map(Post, b.stream(filter_by=['comment']))
for post in stream:
steem.api.getContent('hellocrypto', '5', function (err, result) {
var str = result['body'];
if(str.match('@야매코딩')) console.log("찾았다");

});
except:
print("뀨")

이렇게 넣으면 되는거야?

호오.. 스팀 개발도 이 글 보다보니 관심이 생기네요.. 파이썬 기반인가요?

감사합니다. 알려주신대로 해서 돌려보고 있는데요
아주 아주 잘됩니다. 신기하게도
메모를 여러개 적어두고 랜덤하게 나가게 할 수 도 있을까요?
한 게시물안에 같은 내용만 쭉 보이니까.. 별로라
https://steemit.com/kr-gazua/@dailypro/kr-gazua-newbie-02220180420t233316651z

상당히 친절하게 설명해 주셨네요!
많은 도움이 될 것 같습니다 : )

포스트인지 댓글인지 확인하는 과정을 빼먹은 크립토님... ㅋㅋㅋㅋ

헉 그러네요...ㅋㅋ is_comment() / is_main_post()를 쓰면 되는데, 다음 편에 꼭 넣어둘게요 하핳

ㅎㅎㅎ :D 설명하시면 얻어먹어야징...

여기까지만 해도 제가 궁금했던 내용 대부분이 들어있네요 ㅎㅎ 감사합니다.

혹시 텔레그램으로 스팀잇에 대댓글다는 기능도 구현할 수 있나요??
텔레그램의 steem alert로 새 댓글 달린건 확인하고 있는데, 대댓글을 달기 위해서 스팀잇 들어오는게 너무 귀찮더라고요 ㅋㅋ


이 댓글도 읽어오네요 ㅋㅋ 잘 작동되고 있는것 같아 만족스럽습니다

이건 텔레그램으로 연결하는것 까지 해야해서 너무 어렵겠죠...?
특정 '글쓴이'의 글에 댓글다는 건 별로 안어려워보이는데 가능할까요??

이번에는 주말을 이용해서 천천히 해봐야겠네요 ㅎㅎ 상병 크립토님 좋은 포스팅 응원해요오!! :) 감사감사!

월요일부터 실전연습 들어갑니다!

공부 해야겠어요 공부 공부 공부 ~
좋은 정보 감사합니다. 아직 실습을 안해서 곧 해보겠니다.

@야매코딩
테스트 해봐야겠네요! ㅎㅎ

규.png
잘 됬습니다! ㅎㅎ

Hithere.png
이것도 됬네요! 반신반의했는데 정말로 되어버렸습니다...+_+
야레야레 나란 닝겐... 정말로 해내버렸다구?(훗!)

@야매코딩 잘되라 ~ 실시간이라매...

1.jpeg
왜 포스팅이 안달릴까요 아~~~

@야매코딩 15분전에 댓글달았잖아 찾아봐봐

자동봇으로 하고 싶은 내용
매일 뉴비지원 이벤트를 진행중입니다. 참여자는 평균 30명
이분들께 소소한 봇들을 소환해서 댓글 참여자에게 보팅해 드리고 있습니다

당일 글 한정
댓글 permlink를 소환하는 봇에게 메모로 적고, 일정금액을 전송하고 싶습니다.
정말 많이 고민하고 배우고 있습니다. ~!!! 긴글 자세히 적어주셔 감사합니다. !!!

Hi there!

나이스 성공 !!!!

@야매코딩 언제쯤이면

click here!
click here!This post received a 44% upvote from @krwhale thanks to @hellocrypto! For more information, 이 글은 @hellocrypto님의 소중한 스팀/스팀달러를 지원 받아 44% 보팅 후 작성한 글입니다. 이 글에 대한 자세한 정보를 원하시면,

@나와라봇

얍얍 소환!

안녕하세요 봇 테스트 중입니다.

성공했네요 ㅎ

@기생폴 안녕

Hi there!

ㅋㅋ 성공ㅋ

vim으로 작성하기가 까다로운데 GCP는 ssh이외에 sftp는 지원안되나요? local에서 파일 수정하고 sftp로 그냥 업로드하면 편할 것 같아서요.

@스냅백 소환

@스냅백 소환