굳헬로의 스팀 프로그램 일기!! 열두번째 #12 스팀엔진 토큰 임대내역 추적. 쉽지 않았던 머나먼 여정 (2/2) 스팀엔진 토큰 임대내역 추적 완료!!

in #sct5 years ago (edited)

steem.jpg

월요일 잘 보내고 계신가요??

저는 휴가중이라 늦잠을 자고 싶었지만... 이상하게 평소보다 더 일찍 일어나서는... 피곤한 하루를 보내고 있는 중입니다.

현재 시골로 여행을 와 있는데, 아들님과 놀아준다고... 쉽지 않은 하루를 보내고 있네요.

그래도 잠시 짬 날때마다 프로그램 일기를 작성하고 있답니다.


어제 스팀엔진 토큰 임대내역 추적을 끝까지 마무리 못해 아쉬웠는데... 오늘 마무리 지어 보겠습니다.

스팀엔진 블록익스플로러 https://steem-engine.rocks/@team1p 사이트에서 BeautifulSoup 를 이용해 원하는 정보를 가져오는 방법을 알게 되었으니 이제 이 정보를 이용해 delegate 정보를 추출해 보겠습니다.

누군가 임대를 하게 되면 이렇게 delegate 정보가 출력됩니다.

크롬 관리자 모드에서 소스를 확인하니 <div class="badge badge-primary">delegate</div>코드를 발견할 수 있네요.

만약 delegate 정보가 아니라면 이 코드가 없을것 입니다.

for action in soup.select("span[class='action']") :

어제 만든 <span class="action">...</span> 을 찾는 반복문을 통해 만들어진 action 에서 delegate 정보가 있는지 없는지를 검사를 하면 이 내역이 임대 내역인지 아닌지를 확인가능하겠네요.

for action in soup.select("span[class='action']") :
    for delegate in action.select("div[class='badge badge-primary']") :
        if delegate.text == "delegate" :
            print(action.text)

이렇게 앞에서 만든 action에서 다시 div[class='badge badge-primary'] 코드를 찾아서 반복문을 돌리면서 delegate가 있는지 여부를 검사합니다.

임대내역이 아니라면 그냥 넘어가고 임대내역이라면 출력이 되는거죠.

이제 임대 내역 정보를 찾았으니, 이를 분석해서 필요한 정보만을 빼내도록 하겠습니다.

필요한 정보는 누가 누구에게 어떤 토큰을 얼마나 임대했는가 입니다.

먼저 임대를 보낸 계정명은

sender = action.find("a")

이렇게 action에서 a 태그를 찾아서 sender에 저장했습니다.

그리고 임대를 받는 계정명과 어떤 토큰인지 수량은 얼마인지는

이렇게 <span title="{ ... }">.</span> 여기에 json 형태로 다 들어 있네요.

그럼 이데이터를 가져와 보겠습니다.

data = title["title"].replace("\n", "")
data = data.replace(" ", "")
data = data.replace("\"", '\"')
json_data = json.loads(data)

이 데이터를 가져와 data에 저장을 했는데, 생각과는 달리 json 데이터가 아니더군요.

그래서 json 데이터로 바꾸어 주었답니다.

print(sender.text + " delegate : " + json_data["quantity"] + " " + json_data["symbol"]

그리고 출력을 해보았습니다.

임대 내역이 잘 나오네요.

이 내역을 가지고 계정마다 총합을 구하면 각 계정별 임대 내역이 완성이 되겠네요.

find = "SCT"
dict = {}
if  json_data["symbol"] == find :   
     if sender.text in dict :
        dict[sender.text] = int(dict[sender.text]) + int(json_data["quantity"])
    else :
        dict[sender.text] = int(json_data["quantity"])

각 계정별로 SCT의 임대내역의 총합을 구할수 있도록 코드를 만들어 보았습니다.

find = "SCT" 임대량 확인할 대상을 SCT로 정하고

dict = {} dict는 사전(딕셔너리)라는 파이썬에서 가장 편리한 자료형 중 하나로, 키와 값을 묶어서 저장을 할 수 있는데, 각 계정별 임대량의 합을 구하기 위해 사용하였답니다. dict 안에 계정이 없으면 계정 키 값에 초기 임대 수량을 넣고 이 후 계정별로 계속 합을 구해서 최종적인 임대량을 구해냈습니다.

참... 빠진게 하나 있는데, 임대 회수하는 경우도 있는데, 이것도 같은 방식으로 구해 올 수 있답니다.

임대 회수는 undelegate를 찾아서 계산하면 됩니다.

elif delegate.text == "undelegate" :
    sender = action.find("a")
    title = action.find(attrs={"title" : True})                
    data = title["title"].replace("\n", "")
    data = data.replace(" ", "")
    data = data.replace("\"", '\"')
    json_data = json.loads(data)     
    if  json_data["symbol"] == find :           
        undelegate_sum = undelegate_sum + int(json_data["quantity"])
        print(sender.text + " undelegate : " + json_data["quantity"] + " " + json_data["symbol"])                
        if sender.text in dict :
            dict[sender.text] = int(dict[sender.text]) - int(json_data["quantity"])
        else :
            dict[sender.text] = int(json_data["quantity"])

delegate.text 가 undelegate 인것을 찾아내어 위에서와 같이 계정별로 그 값을 빼서 최종적인 임대량에 반영합니다.

그리고 또 하나 빠진것이 있는데...

https://steem-engine.rocks/@team1p 에 접속하면 1페이지에 해당하는 분량만 보여지기에, 모든 블록의 값이 나오지 않습니다.

제대로 된 값을 계산하려면 모든 페이지를 다 검사해야 합니다.

2페이지를 확인해보니 주소가 https://steem-engine.rocks/@team1p?page=2이더군요.

주소창 마지막에 page=1, 2, 3 이런식으로 페이지가 구분됩니다.

총 7페이지 이기에 7페이지를 모두 검사하여야 합니다.

last_page = 7
for page in range(1, last_page + 1):
    url = "https://steem-engine.rocks/@" + username
    params = {'page': page}
    r = requests.get(url, params=params ) 
    soup = BeautifulSoup(r.text, 'html.parser')

그러기 위하여 모든 페이지를 검사할 수 있게 for 반복문을 추가하여, 1페이지부터 마지막 페이지까지 다 검사하는 코드를 추가하였습니다.

dsum = 0
for s in dict :
    dsum = dsum + dict[s]
    print(s + " : " + str(dict[s]) + " 지분율 : %.2f %%" % (int(dict[s]) / (delegate_sum-undelegate_sum) * 100) )

print("임대 총합 : ", dsum)

마지막으로 각 계정별로 임대량을 출력하고, 지분율까지 계산되도록 코드를 만들어 보았습니다.

이제 마무리를 해보겠습니다.

import json
import requests
from bs4 import BeautifulSoup

username = "team1p"
find = "SCT"
delegate_sum = 0
undelegate_sum = 0
last_page = 7
dict = {}
for page in range(1, last_page + 1):     
    url = "https://steem-engine.rocks/@" + username
    params = {'page': page}
    r = requests.get(url, params=params ) 
    soup = BeautifulSoup(r.text, 'html.parser')    

    for action in soup.select("span[class='action']") :
        for delegate in action.select("div[class='badge badge-primary']") :
            if delegate.text == "delegate" :               
                sender = action.find("a")
                title = action.find(attrs={"title" : True})                
                data = title["title"].replace("\n", "")
                data = data.replace(" ", "")
                data = data.replace("\"", '\"')
                json_data = json.loads(data)   
                if find == json_data["symbol"] :
                    delegate_sum = delegate_sum + int(json_data["quantity"])
                    print(sender.text + " delegate : " + json_data["quantity"] + " " + json_data["symbol"])              
                    if sender.text in dict :
                        dict[sender.text] = int(dict[sender.text]) + int(json_data["quantity"])
                    else :
                        dict[sender.text] = int(json_data["quantity"])
            elif delegate.text == "undelegate" :
                sender = action.find("a")
                title = action.find(attrs={"title" : True})                
                data = title["title"].replace("\n", "")
                data = data.replace(" ", "")
                data = data.replace("\"", '\"')
                json_data = json.loads(data)                
                if find == json_data["symbol"] : 
                    undelegate_sum = undelegate_sum + int(json_data["quantity"])
                    print(sender.text + " undelegate : " + json_data["quantity"] + " " + json_data["symbol"])
                    if sender.text in dict :
                        dict[sender.text] = int(dict[sender.text]) - int(json_data["quantity"])
                    else :
                        dict[sender.text] = 0 - int(json_data["quantity"])
print("delegate : ", delegate_sum)
print("undelegate : ", undelegate_sum)
print("delegate_sum_sum : ", delegate_sum-undelegate_sum)

dsum = 0
for s in dict :
    dsum = dsum + dict[s]
    print(s + " : " + str(dict[s]) + " 지분율 : %.2f %%" % (int(dict[s]) / (delegate_sum-undelegate_sum) * 100) )

print("임대 총합 : ", dsum)

완성되었네요.

username = "team1p"
find = "SCT"
last_page = 7

임대량 확인하고 싶은 계정명을 username에 넣으시고

검사하고 싶은 토큰명을 find에 넣으시고

https://steem-engine.rocks/@계정명 에서 몇 페이지인지 확인하여 last_page에 그 값을 넣으시고

프로그램을 실행하면

짜잔~

team1p에 임대된 SCT의 총합은 144708이며, 각 계정별로 지분율까지 확인됩니다.

다만 페이지별로 정보를 긁어와 분석하고 원하는 자료를 뽑는데 시간이 걸릴수 있으니, 잠시 1-2분 정도 기다려야 하네요.

이제 조합에서는 이 자료를 바탕으로 앞전에 공부한 자동 클레임과 자동 전송 기능을 추가하여 조합원들에게 자동으로 분배 가능한 프로그램으로 활용할 수 있을거라 생각합니다.

그리고 앞으로 이 코드를 웹으로 실행해서 누구나 쉽게 어떤 계정에 어떤 토큰이 얼마나 임대되었는지 확인할 수 있도록 만들 예정입니다.

다소 시간이 걸리겠지만, 완성되면 유용하게 사용될지도 모르겠네요.

앞으로도 굳헬로의 프로그램 일기 기대해 주시기 바랍니다.


굳헬로의 스팀 프로그램 일기!! 시리즈

#1 굳헬로의 스팀 프로그램 일기!! 대망의 시작 #1 Python 프로그램 설치 && steemengine 파이썬 api 설치 && 간단한 steemengine 예제

#2 굳헬로의 스팀 프로그램 일기!! 그 두번째 #2 비주얼 스튜디오 코드 프로그램 설치 && 비주얼 스튜디오 코드를 사용하여 파이썬 다루기 && 간단한 steemengine 예제

#3 굳헬로의 스팀 프로그램 일기!! 세번째 #3 스팀엔진 토큰의 정보를 가져오는 findOne() && 누군가의 토큰 사용 내역을 가져오는 get_history() && JSON 데이터 출력

#4 굳헬로의 스팀 프로그램 일기!! 네번째 #4 steemengine Token 클래스 && Token.get_holder() && Token.get_market_info() && Token.get_buy_book() && Token.get_sell_book()

#5 굳헬로의 스팀 프로그램 일기!! 다섯번째 #5 스팀엔진 블록을 뒤져서 원하는 정보를 찾아보자!! 스팀엔진 마켓 거래 내역을 뽑아내는 예제

#6 굳헬로의 스팀 프로그램 일기!! 여섯번째 #6 파이썬으로 스팀엔진 토큰들을 클레임 해보자.

#7 굳헬로의 스팀 프로그램 일기!! 일곱번째 #7 프로그램 일기도 어느덧 1주일!! 드디어 첫 실전!! 무한 반복 작업 수행하기!! 이제 직접 클레임 하는 손맛은 잊자. 무한 반복 자동 클레임!!

#8 굳헬로의 스팀 프로그램 일기!! 여덟번째 #8 텔레그램 봇을 이용해 알림을 받아보자!! && 무한 반복 자동 클레임의 정보를 텔레그램으로 받아보기!!

#9 굳헬로의 스팀 프로그램 일기!! 아홉번째 #9 무한 반복 자동 클레임 업그레이드!! && 토큰 잔고 확인 && 토큰 전송과 토큰 전송 내역을 텔레그램으로 받아보기!!

#10 굳헬로의 스팀 프로그램 일기!! 열번째 #10 토큰 전송내역을 검사하고, 토큰을 전송 받으면 텔레그램으로 알림을 받아보기!!

#11 굳헬로의 스팀 프로그램 일기!! 열한번째 #11 스팀엔진 토큰 임대내역 추적. 쉽지 않았던 머나먼 여정 (1/2)

Sort:  

promisteem님이 goodhello님을 멘션하셨습니당. 아래 링크를 누르시면 연결되용~ ^^
promisteem님의 [투자결과보고] 프로미스팀의 13번째 달 투자수익률을 공개합니다! (투자자 모집공고)

...
innomano innovit danbain hwook glory7 jisui hodolbak bramd goodhelloepitt925 parkname songa0906 illluck
투자금 분배 상세...

굿헬로님 포스팅 잘 보고 있습니다. 근데 그냥 보고만 있네요. 따라해야 하는데..

ㅎㅎ 한번 따라 해보세요.

앞으로 스몬 자동화도 연재해볼 생각이니, 미리 조금씩 감을 익혀두면 좋을것 같습니다.

ㅎㅎㅎ 그러게요 ㅎㅎㅎ

음... 저도 그냥 보기만 ...ㅋㅋㅋㅋㅋ 벌써 하루가 다 가네요!! 수고하셨습니다~

ㅎㅎ 한번 따라해 보시죠~

naha.sct님이 goodhello님을 멘션하셨습니당. 아래 링크를 누르시면 연결되용~ ^^
naha.sct님의 나풀나풀 나하풀 소식 190729.1835 (신규모집 7월30일 마감)

...100
feelsogood.cur 550
fur2002ks 100
garamee21 100
goodhello 3000
hyokhyok 3000
iieeiieeii 400
influencer07 4...

나날이 발전하시는 군요 ㅎ

ㅎㅎ 진작에 해볼껄 그랬어요~

이렇게 열심히 코딩하시면 술은 언제 드시나요??? ㅎㅎ

술 마시다 짬짬히 코딩합니다~ ㅎㅎㅎㅎㅎ

Congratulations @goodhello! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You distributed more than 21000 upvotes. Your next target is to reach 22000 upvotes.

You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Hi @goodhello!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 3.949 which ranks you at #4237 across all Steem accounts.
Your rank has improved 10 places in the last three days (old rank 4247).

In our last Algorithmic Curation Round, consisting of 133 contributions, your post is ranked at #78.

Evaluation of your UA score:
  • You're on the right track, try to gather more followers.
  • The readers appreciate your great work!
  • You have already shown user engagement, try to improve it further.

Feel free to join our @steem-ua Discord server

union.sct님이 goodhello님을 멘션하셨습니당. 아래 링크를 누르시면 연결되용~ ^^
union.sct님의 [공지] 스판유니언 조합원 대상 13차 큐레이션 수익배분 완료 안내

...% 6 31 2차 추가 goodhello/td> 1000 1.16% 6 ...

Thank you for your continued support towards JJM. For each 1000 JJM you are holding, you can get an additional 1% of upvote. 10,000JJM would give you a 11% daily voting from the 700K SP virus707 account.

Coin Marketplace

STEEM 0.29
TRX 0.12
JST 0.032
BTC 63423.66
ETH 3077.69
USDT 1.00
SBD 3.87