Показать всё, что скрыто или Блокчейн помнит всё. Пособие по сбору статистики Golos при помощи Python для чайников.


Давненько я не писал ничего про Python. Как-то не было особо поводов.
Но, в прошлую пятницу меня неожиданно посетила мысль, а почему бы не провести анализ данных по своему блогу? А именно, собрать информацию по подписчикам, СГ подписчиков, проанализировать апвойты и флаги. Просто, just for fun. Ну и заодно, появится причина запилить что-нибудь на Голос.
Дополнительным катализатором процесса послужил материал от @sci-populi, где они ссылаются на мои статьи про Piston. В целом, приятно, что мои опусы читает кто-то кроме меня)
Думаю, статистика по моему блогу мало кому интересна, а вот информация о методах сбора этой статистики возможно может быть для кого-то полезной.

Итак, существует два способа вытянуть данные из блокчейн:

1. Piston-Lib и обращение непосредственно к какой-либо ноде
Здесь мы вытаскиваем информацию непосредственно из цепочки блоков.
Используя соответствующие методы piston-lib мы можем парсить блоки, получать информацию о каком-либо аккаунте, запрашивать историю аккаунта, получать посты, либо комментарии удовлетворяющие определённому условию. В общем, многое. Подробнее о использовании piston-lib можно узнать на официальном сайте
Например, код ниже получает историю апвойтов по определённому аккаунту:

from piston import Steem
from piston.account import Account
a = Account("gmaster")
golos = Steem('wss://ws.golos.io', wif = "5K....")
history_events = a.history(filter_by=['vote'], start=0)

На первый взгляд всё просто и лаконично. Что, впрочем, не удивительно, это-ж Python).
Но, если вы делаете сложные, либо массовые запросы, данный способ не является оптимальным, а скорее всего даже вреден, так как в этом случае Вы можете создать повышенную нагрузку на ту ноду, к которой подключаетесь, что может негативно сказаться на её работе. Поэтому, лучше использовать способ №2.

2. Получаем информацию из GolosSQL
На самом деле для сбора статистики, не обязательно обращаться напрямую к блокчейн. Для того, чтобы не насиловать ноды, можно воспользоваться сервисом уважаемого @arcange, подключившись к его серверу БД MSSQL
В данную БД пишется вся информация из блокчейн(ну может и не вся, но для сбора статистики есть полный набор данных). Соответственно, можно делать выборку из БД, отправляя ей обычные SQL запросы и играться с полученными данными как Вашей душе будет угодно.
Используя Python это можно делать буквально в пару строчек:
Для начала импортируем ORM SQLAlchemy и модуль pymssql для работы с БД, задаём параметры подключения и запускаем процедуру create_engine

import pymssql
from sqlalchemy import create_engine
url = 'mssql+pymssql://golos:golos@sql.golos.cloud/DBGolos'
golosDB = create_engine(url)

Далее, создаём подключение, формируем и отправляем нужный SQL запрос

connection = golosDB.connect()
query = """
select
    voter as Voter,
    count(*) as count
from TxVotes
where author = 'gmaster'
group by Voter
order by count desc
"""
result = connection.execute(query)

В данном случае я получаю список всех, кто голосовал за мои посты и комментарии, количество апвойтов и сортирую их по убыванию.
Полученные данные мы можем обрабатывать как угодно, например стоить графики, диаграммки, схемы при помощи pandas, либо производить различные вычисления. В моём случае этого не требуется, так как вся необходимая информация доступна без этого, формирование нужных столбцов и подсчёт апвойтов происходит сразу в SQL запросе.
Следующим этапом можно вывести результат запроса непосредственно в файл. Нужно расставить дополнительные метки, чтобы в итоге получилась markdown табличка, которую достаточно просто скопировать и вставить на страничку

result = connection.execute(votes)
with open("test_stat.md","w") as out:
    print(' | Upvoter | Количество апвойтов | ', file=out)
    print(' |-----|-----| ', file=out)
    for res in result:
          print(' | ' + res[0]+ ' | ' + str(res[1]) + ' | ', file=out)

В итоге выходит что-то по типу этого:

Upvoter Количество апвойтов
gmaster 64
dobryj.kit 22
zhenek 21
gryph0n 17
borishaifa2 17
tengri 17
golosboard 16
inkognito 16
grkh 16
kedgaks 16
natulya 15

Просмотреть структуру GolosDB, можно при помощи подключения через любое внешнее приложение

enter image description here
Например, здесь мы видим табличку Comments содержащую все комментарии и статьи Голос. Отличить пост от комментария просто, у поста поле parent_author пустое.
SQL достаточно мощный язык и правильно формируя запросы можно быстро получать нужную информацию без необходимости дополнительного анализа. Например, отправив запрос:

query = """
select
    author as Author,
    count(*) as count
from TxComments
where body LIKE '%python%'
group by Author
order by count desc
"""

Получим топ пользователей, которые упоминают в постах и комментариях Python
Author Количество упоминаний Python
@habreplicator 91
@pythono 44
@golosboard 25
@iamraa 21
@blockchained 19
@dobryj.kit 16
@kiwi 16
@sxiii 15
@gmaster 14
@t3ran13 13
@sept 11
@darkvasyak 10
@naminutku 8
@tengri 8
@tristamoff 8
@mapala 7
@prismo 7
@wealthycat 7
@archibald116 6
@gelmut 6

Либо, можем получить топ 10 постов по количеству апвойтов за 2017 год:

select top 10 author, permlink, net_votes
from Comments
where
    cast(created as date) > '2017-01-01'
    and parent_author = ''
    and author <> 'golos.loto'
    and author <> 'bm-bmtasks'
order by net_votes desc

Дабы список получился релевантным мы исключаем из результатов запроса golos.loto и аккаунт, который организовывал какие-то сходки Бизнес Молодость

Author Permlink Количество апвойтов
blockchained anons-zapusk-shlyuza-i-start-torgov-golos-i-gbg-na-decentralizovannoi-torgovoi-platforme-bitshares-rudex-s-0-komissiei 445
golosmedia gmnauka0409 429
golosmedia golosmediacorp 417
golosmedia gmbiz0209 416
golos obnovlenie-veb-klienta-golos-io 402
golosmedia newrules 399
lira proshu-minutu-vnimaniya-u-nashego-jurgan-beda 388
golosmedia psk61 386
arcange sleduyushii-khardfork-opyat-otlozhen-moe-vyrazhenie-nedovolstva 385

Вот как-то так.
Применение данных средств ограничено только Вашей фантазией.
Главное, не использовать их в деструктивных целях.
За сим откланяюсь.
Буду рад Вашим апвойтам, подпискам или репостам.
@gmaster


Comments 16


чет я даже и не припомню=)

06.09.2017 18:03
0

python и @pythono видимо по запросу были идентичны?

06.09.2017 18:37
0

так и есть там же LIKE '%python%'

06.09.2017 19:47
0

=) точно) об рейтинге я не подумал)

06.09.2017 18:41
0

апвойт!

06.09.2017 19:47
0

Очень интересно! Добавил в закладки!

07.09.2017 02:39
0

Здравствуйте!

На платформе Голос в первую очередь ценится уникальный авторский контент, который ранее нигде не публиковался.

Ваш пост поддержан в рамках программы "Поддержка авторского уникального контента", скоро за него проголосует - @sept или @dmilash со 100% силой, если они не проголосуют - вам будут перечислены 12,5 gbg с аккаунта @septcur или @dailystats.

Желаем вам творческого роста и увеличения авторских наград.

07.09.2017 04:41
0

Отличный пост!
Чтобы сделать разницу между пост и комментарий, лучше использовать comments.depth
comments.depth = 0 -> пост
comments.depth > 0 -> комментарий

07.09.2017 08:45
0

Спасибо за совет. Действительно, как то я упустил мысль, что с этим полем будет работать удобнее.
И за GolosSQL спасибо, крутая штука)

07.09.2017 09:11
0

спасибо за пост очень интересно отметил себе несколько подписочек новых

08.09.2017 16:24
0

хочу побеспокоить @gmaster и спросить за piston-cli
делаю попытку апнуть, предположим этот пост

piston upvote @piranya/gusenichki

выдается ошибка:

er01 er02

с чем может быть это связано? считать информацию из блокчейна можно, а записать - нет? (ни пост, ни ап)

13.09.2017 20:08
0

Нужно указать параметр weight и аккаунт, если у Вас используется несколько постинг ключей
pisto.png

14.09.2017 11:39
0

указывал, аналогично.

предыдущими командами показал, что постинг и аккаунт настроен по умолчанию, а вес по умолчанию 100 и его можно не указывать

есть подозрение что, для винды еще чего-то не хватает в установке, что-то упущено

P.S. да вы кудесник, таки получилось по Вашему, огромная благодарность

14.09.2017 12:49
0

Почему-то не пришло уведомление, что Вы обновили комментарий, поэтому увидел его только сейчас.
Рад, что смог помочь))

16.09.2017 16:50
0