[DA series - Learn Python with Steem #09] Steem 小工具DIY #1 - 我的Steem小偵探

[DA series - Learn Python with Steem] 是DA(@deanliu & @antonsteemit)關於「從Python程式語言實做Steem區塊鏈的入門」的系列,歡迎趕緊入列學習!

前情提要:[DA series - Learn Python with Steem #08] 函式庫(Modules)

第#09堂課,今天我們正式開始玩Steem階段!今天試試看來做做「我的Steem小偵探」!

Steem 小工具DIY #1 - 我的Steem小偵探

經過了好幾篇的介紹,我們總算是把python編程的基礎都帶過了,剩下的我們就一邊做點有趣的事情一邊學習吧!

上次教學的最後面我們學會了安裝並導入steem-python,並且成功寫了第一支用來偷看別人帳號錢包餘額的程式(check_balance.py)。今天我們來做稍微進階一點的腳本,大家來練習抓取自己想要「觀察」一個帳號時,最想知道的資訊。在開始之前,先告訴大家,所有關於steem-python這個套件包的指令都可以在Steem-Python Documentation這官方文件中找到,裡面的函式非常多,我也不會全部用到。若是大家有其他我範例之外想要抓取的資訊,可以先到這個Documentation裡面搜尋看看,照理說看完今天的介紹,應該大家都會比較了解如何看著Documentation自我學習啦!

首先我們可以先看看上週用到的程式:

account_name = sys.argv[1]
s = Steem()
balance = s.get_account(account_name)['sbd_balance']
print(balance)

可以看出,我們是首先創件了一個Steem的Class,接著透過裡面一個叫做get_account的method來取得他SBD 餘額資料。我們可以到剛剛提到的官方文件中,搜尋關於get_account這個method的更多敘述:

由敘述的Return type: dict我們可以知道:這個method會回傳給我們一個存滿了各種使用者資訊的dictionary。我們再回頭看看剛剛的範例寫法:

balance = s.get_account(account_name)['sbd_balance']

沒錯! s.get_account(account_name)如果是一個字典的話,那麼後面使用括號的 ['sbd_balance']來取得這個字典中的SBD餘額,看起來就真的太合理了。沒錯,就這麼簡單,我們可能有更多想要的資訊存在s.get_account(account_name)裡面,不如我們先想辦法印出所有的key - value來看看吧!

from steem import Steem
import sys

account_name = sys.argv[1]
s = Steem()
account_info = s.get_account(account_name)

for key, value in account_info.items():
    print('----------')
    print(key)
    print(value)

這裡我們要教一個新的技巧,如何走遍一個dictionary並且把所有東西印出來。當然了,你可以直接print(account_info)把所有東西印出來,但是格式會很亂很複雜;因此可以使用dictionary內建的.items() method。這個method會把所有dictionary裡面的每個key-value變成一個List of tuple。tuple可以想像成「綁定」的多個物件,因此整個method會回傳的東西就是一個List,內含許多兩兩綁定的元素:[(key1, value1) ,(key2, value2) ,(key3, value3),...]。

在python的迴圈裡,如果我們知道走過得這個list裡面的東西都是兩兩綁定的,我們可以直接用我們上面的寫法,直接用不同的變數表示一個Tuple (key_A, value_A)裡的元素。這就是為什麼我們使用for key, value in這樣的寫法,如此一來當我們走到這個List裡面的第一個tuple時,key就直接代表了tuple裡面的第一個數值,而value就直接代表tuple裡面的第二個數值。如果你看得不明白沒關係,執行看看就會了解囉!

執行程式python check_info.py antonsteemit

----------
last_account_update
2018-07-12T14:16:45
----------
post_count
855
----------
savings_sbd_seconds_last_update
2017-12-19T09:36:33
(...)
----------
guest_bloggers
[]
----------
savings_sbd_seconds
0

天阿!直接列印出一大堆一大堆有的沒有的東西出來。當然了,其中有些可能滿重要的,如果是我想要的,我接著就可以透過他的key來存取它。依據我們剛剛規定的格式「------」下面第一行是字典的key名稱,再下來是值。我就稍微找了一下我對於一個account有興趣的幾個項目:例如我找了 post_count(文章&留言數), voting_power, reputation,last_root_post(上次po文)

找到這些好玩的key之後,我們就可以透過他們來存取剛剛dictionary中這些我們想要的值了。因此我們先把程式改成以下寫法:

from steem import Steem
import sys

account_name = sys.argv[1]
s = Steem()
account_info = s.get_account(account_name)

post_count = account_info['post_count']
voting_power = account_info['voting_power']
reputation = account_info['reputation']
last_post_date = account_info['last_root_post']

display_message = '''
Username: \t{}
Reputation:\t{}
=============================
Total Posts:\t{}
Last Post: \t{}
Voting Power:\t{} %
'''.format(account_name, reputation, post_count, last_post_date, voting_power)

print(display_message)

其中最後一段的display_message一樣是個字串,不過我們可以使用''' '''這樣符號來定義「包含換行的字串」。後面.format()的用法跟以前介紹的相同,就是把.format()裡面的變數依序填到前面字串的框框裡。執行完這段程式之後我們會發現有一些小問題:

Username:   antonsteemit
Reputation: 6266755755483
=============================
Total Posts:    855
Last Post:  2018-07-29T16:15:24
Voting Power:   8696 %

其中Reputation好像是個奇怪的數字,有點不合理;再來Voting Power也是應該介於0~100之間,最後那個Last Post的日期格式有點醜。我們就來針對這三點做一點修正。

我馬上去Google,Steem Reputation 是怎麼計算的。果然馬上搜到一篇文章告訴我們,要如何把這個raw_reputation換算成1~100的名聲值。其中會用到log這個函數,而這個函數是在一個python內建的函式庫math裡面,因此我要在我的程式最上面加入import math導入此函式庫,接著把這個算式用python寫出來:

reputation = (math.log10(int(reputation))-9)*9+25

如此一來reputation就正常了。接下來來看看Voting Power。一樣Google之後發現很簡單,原來只要除100就是我們平常說的Voting Power了,所以我們也把Voting Power除100:

voting_power = int(voting_power)/100

剩下最後一個有點難看的是「時間格式」。現在的時間格式是含有T的ISO 8601格式,一樣可以使用一個python的套件dateutil來解析:

last_post_date = parser.parse(last_post_date)

解析之後last_post_date會成為一個DateTime 物件。還有另外一個常用的套件就叫做datetime,我們可以透過他獲取「現在時間」,並且透過兩者相減來獲得「距離上次po文時間」

time_since_last_post = datetime.datetime.now() - last_post_date
days_since_last_post = time_since_last_post.days

最後我的days_since_last_post就會是距離上次發文的天數了。所以我把這些東西都加到最後的display_message裡,最後完整的程式如下(可以參考此處原始碼):

from steem import Steem
import sys
import math
from dateutil import parser
import datetime

account_name = sys.argv[1]
s = Steem()
account_info = s.get_account(account_name)

post_count = account_info['post_count']
voting_power = account_info['voting_power']
reputation = account_info['reputation']
last_post_date = account_info['last_root_post']

reputation = (math.log10(int(reputation))-9)*9+25
voting_power = int(voting_power)/100
last_post_date = parser.parse(last_post_date)
time_since_last_post = datetime.datetime.now() - last_post_date
days_since_last_post = time_since_last_post.days

display_message = '''
Username: \t{}
Reputation:\t{}
=============================
Total Posts:\t{}
Last Post: \t{} ({} days ago)
Voting Power:\t{} %
'''.format(account_name, reputation, post_count, last_post_date, days_since_last_post, voting_power)

print(display_message)

執行結果:

怎麼樣,滿可愛的吧~

希望這樣的介紹可以幫助大家學習怎麼「自我教學」啦!雖然今天的例子只有用到get_account()而已,但是它提供的訊息也遠不只這些,回家作業就讓大家試試看作出自己的小偵探,再以起來分享吧!當然也可以去官方文件偷偷先學其他功能更強大的function來使用喔~

我們下篇文章再見囉~下課!

課堂助教 @deanliu表示,最近剛剛開始進入玩Steem階段,甚至有些人安裝還不順利,下週開始課堂頻率會降低,讓大家能夠好好把握時間學習好,否則到最後都沒人在學了,殊為可惜~~ 或是還沒開始學的同學,也歡迎趕緊去前面補課Python,趕緊加入我們Learn Python with Steem的行列中來吧!^_^

有問題請持續在系列帖中發問,會請 @antonsteemit老師或是有經驗的其他高手同學有空來解惑的~~

class-377117_1280.jpg
image - pixabay

Sort:  

image.png
随意找了一个get_account_bandwidth,然而我没看懂~最后跑去看源文件,还是没明白红线部分,找了别人的写的代码,只知道bandwidth_type:object有三种“post”、“forum”、“market”,原因什么完全不知道~谁来指教下,多谢!

如果去看document會發現我們現在所作的事情都是被包含在「steemd api」這下面,也就是說其實我們只是在呼叫節點,並且請他們幫我們查詢某些結果。
所以這段程式其實沒有解釋什麼,只是說了我們用的s.get_account_bandwidth()這個method,其實只是再去呼叫另外一個叫做call()的method,附帶那些「要向api詢問的參數」。
而這個call()就是「call api」的意思,負責問節點不同的問題。在這個例子中就是詢問get_account_bandwidth結果。
所以雖然做的事情好像有點冗,寫一個method讓我們呼叫另外一個method來跟api溝通,但是整體而言這樣的使用界面是比較好的。

至於bandwidth_type,其實我沒有研究過(原來分這麼多種阿~)。我猜post跟market指的應該是「發文」跟在steem market的操作的使用額度,forum可能是follow等等操作吧。

哦~大概理解了,多谢指教!🙇‍♀️

hw8.png

成功,晚點再試試抓取其他數據,謝謝教學!

I'm interested in learning the python program but unfortunately I don't read Chinese language. I'll really appreciate it, if u can also write an English version in order to cover a wider audience in steemit.

Thanks.

Sorry, there won't be an English version any time soon. If google translate cannot satisfy you, I am sure that there are many free resources out there for learning Python by yourself.

We have enough work for us preparing for these teaching materials and do not have the capacity to do bilingual posts. Please understand. Thanks and good luck!

I just tried d Google Translator up for the first time with assistance from a friend and it was amazing.

Sorry, there won't be an English version any time soon.

I hope you don't take this the wrong way but I was thinking. Since, there won't be any English version, can I take up d responsibility of doing that and sending it to you to post it along side with the Chinese version or I post it on my blog and make every reference to your blog??

Cheers.

好列害呀

那可不!有問題盡管問啊~~~

我也是醉了,居然没有dateutil,其实我根本不懂安装语句的意思,举一反三的将部分内容替换掉!欧耶!
image.png
image.png
但是看其他的资料好纠结啊,看的我头疼~等@yjcps的课外练习好了,哈哈哈!

我。。。又掉坑里了。。。

坐等你寫此次掉坑爬坑的經歷!

Posted using Partiko Android

Coin Marketplace

STEEM 0.21
TRX 0.25
JST 0.038
BTC 97111.20
ETH 3382.29
USDT 1.00
SBD 3.20