• XSS.stack #1 – первый литературный журнал от юзеров форума

Нужно спарсить Etherscan

BankRoll

RAID-массив
Пользователь
Регистрация
05.11.2022
Сообщения
70
Реакции
25
Депозит
0.0207
Нужно написать простенький парсер по езерскану.
Суть работы следующая: У меня имеется список адресов, среди всей массы этих адресов мне нужно выделить те адреса - у которых в истории транз имеется нужна мне транзакция. На скрине выделил какой столбец нужно парсить, к примеру мне нужны все адреса которые имеют транзакцию "Execute"
Я прописываю этот самый "Execute" в качестве переменной для поиска и парсер начинает в каждом адресе искать транзакцию с таким именем, если находит-сохраняем этот адрес в блокнотик, если нет переходим к следующему адресу. Суть думаю вы поняли.
Главный нюанс это скорость работы софта, хотелось бы добиться минимум 20-30 адресов в секунду и без прокси) такое реально?
Отказ от прокси обосновываю дороговизной чека, есть аналогичный софт у меня - не успеваю пополнять балансы в прокси сервисах.
Возможно минуя etherscan эти данные можно вытащить с паблик нод...
Если у кого есть идеи по реализации и готов взяться за работу-прошу в пм
1700942841580.png
 
отлично, нода нашлась, теперь осталось написать сам скрипт:)
Обманул чутка, потратится все же прийдется, если нужно искать уже существующие транзакции то прийдется работать с etherscan или подобными api (covalent etc)
Если мониторить новые то можно обойтись rpc
 
Обманул чутка, потратится все же прийдется, если нужно искать уже существующие транзакции то прийдется работать с etherscan или подобными api (covalent etc)
Если мониторить новые то можно обойтись rpc
никакого мониторинга, работа только с уже имеющимся транзами
 
требует доработки
использование
установить python3, установить pip, установить зависимости
вставить в код апи ключ etherscan, зарегистрироватся на quicknode, создать eth endpoint, взять websocket url и вставить в код
pip3 install requests web3 colorlog
python3 script.py "C:\wallets.txt" "swap,execute"
файл abis.json будет походу работы заполятся и запросов к etherscan будет все меньше и меньше

Python:
import requests
import logging
from colorlog import ColoredFormatter
from web3 import Web3
import json
import sys
import os

formatter = ColoredFormatter(
    # %(asctime)s - %(name)s - %(levelname)s - %(message)s
    "%(log_color)s%(asctime)s-%(levelname)-5s%(reset)s %(blue)s%(message)s",
    datefmt=None,
    reset=True,
    log_colors={
        'DEBUG':    'cyan',
        'INFO':     'green',
        'WARNING':  'yellow',
        'ERROR':    'red',
        'CRITICAL': 'red,bg_white',
    },
    secondary_log_colors={},
    style='%'
)
logger = logging.getLogger('')
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)

#paste here etherscan api key
ETHERSCAN_API_KEY = ""

#paste here quicknode eth wss endpoint url
#http://sample-endpoint-name.network.quiknode.pro/token-goes-here/
quickNodeWssUrl = ""

abis_cache = {}
if os.path.isfile("abis.json"):
    with open('abis.json') as f:
        abis_cache = json.load(f)
addrs = []
if len(sys.argv) < 3:
    logger.error("need wallets file as fist arg")
    logger.error("need method list as second arg")
    logger.info('ex: script.py "C:\wallets.txt" "swap,execute"')
    quit()

wallets_file = sys.argv[1]
if os.path.isfile(wallets_file):
    with open(wallets_file) as f:
        addrs = f.read().splitlines()
else:
    logger.error("need wallets file as fist arg")
    logger.info('ex: script.py "C:\wallets.txt" "swap,execute"')
    quit()

fn_names = sys.argv[2].lower().strip().split(",")  
is_Connected = False
try:
    if len(quickNodeWssUrl) == 0:
        w3 = Web3(Web3.HTTPProvider("https://rpc.builder0x69.io"))
    else:
        w3 = Web3(Web3.WebsocketProvider(quickNodeWssUrl))
    is_Connected = w3.is_connected()
    logging.info("Connected: "+str(is_Connected))
except Exception as e:
    logger.exception(e)
    quit()

def check_address(addr, types):
    txs = json.loads(requests.get(
        f"https://api.blockcypher.com/v1/eth/main/addrs/{addr}").text)
    if "txrefs" not in txs:
        logger.error("BlockCypher api error")
        return
    for item in txs["txrefs"]:
        tx = w3.eth.get_transaction(item["tx_hash"])
        input = tx["input"]
        if len(input) == 0:
            name = 'transfer'
        else:
            if tx['to'] in abis_cache:
                abi = abis_cache[tx['to']]
            else:
                abi_endpoint = f"https://api.etherscan.io/api?module=contract&action=getabi&address={tx['to']}&apikey={ETHERSCAN_API_KEY}"
                abi = json.loads(requests.get(abi_endpoint).text)
                if abi["message"] == "OK":
                    abi = abi['result']
                    abis_cache[tx['to']] = abi
                else:
                    logger.error("receive abi error: "+abi['result'])
                    continue
            contract = w3.eth.contract(Web3.to_checksum_address(
                tx["to"]), abi=abi, decode_tuples=True)
            function_signature, arguments = contract.decode_function_input(input)
            name = function_signature.fn_name.lower()
        if name in fn_names:
            logger.info(f"{addr} found {name}")
            return

for item in addrs:
    check_address(item, fn_names)
with open("abis.json", "w") as f:
    f.write(json.dumps(abis_cache, indent=4))
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
ETHERSCAN_API_KEY = "ETHERSCAN_API_KEY"
я так понял, что тсу нужно именно парсить, а не через апи.
Если у него это сутками работает, то возьмем, что мы отправляем 4 запроса в секунду, это 345600 запросов в сутки. Это подписка за 300 баксов.

Тс, что дороже прокси или подписка?
Может тебе стоит через подписку делать?


addrs = ["0x18bB7eF333a62Aca82C200d511Bd79C5976050B8"]
а че адреса не спарсил?


C++:
#include <iostream>
#include <string>
#include <vector>

#define CURL_STATICLIB
#include <curl/curl.h>

using namespace std;

#ifdef _DEBUG
#pragma comment(lib, "libcurl_a_debug.lib")
#else
#pragma comment(lib, "libcurl_a.lib")
#endif

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "normaliz.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "wldap32.lib")

size_t writefunc(void* ptr, size_t size, size_t nmemb, string* s) {
    string data(reinterpret_cast<const char*>(ptr), size * nmemb);
    *s += data;
    return size * nmemb;
}

using wallets_list = vector<string>;

wallets_list parse_page_wallets(string content, const string& method_name) {
    wallets_list result;
    const string to_find = "title=\"" + method_name + "\">" + method_name;
    size_t pos = content.find(to_find);

    while (pos != -1) {
        content = content.substr(pos);
        pos = content.find(" data-bs-title=\"0x"); // не предусмотрен парсинг кошельков бирж
        content = content.substr(pos + 16);
        string wallet = content.substr(0, content.find("\">"));
        if (wallet.size() >= 40 && wallet.size() <= 44)
            result.push_back(move(wallet));
        pos = content.find(to_find);
    }

    return result;
}


int main(int argc, char* argv[]) {
    const string trans_method = "Execute"; // метод, который надо парсить
    const string start_page = "https://etherscan.io/txs?ps=100&p=";
    const char useragent[] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36";

    CURL* curl = nullptr;
    CURLcode res;
  
    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();

    if (curl) {
        for (int i = 1; i <= 5000; ++i) {
            string page = start_page + to_string(i);
            string result = "";

            curl_easy_setopt(curl, CURLOPT_URL, page.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
            curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent);
            res = curl_easy_perform(curl);

            if (res) {
                cerr << "something went wrong!" << endl;
                break;
            }

            wallets_list wallets = parse_page_wallets(move(result), trans_method);
            for (const auto& wallet : wallets)
                cout << wallet << endl;
        }
        curl_easy_cleanup(curl);
    }
    else {
        cerr << "libcurl init failed" << endl;
    }

    curl_global_cleanup();
    return 0;
}
накидал за 20 мин, если кому не впадлу, то допилите сюда прокси и проверку этих самых прокси :))
ну и выплюньте тсу
сохранение в файл, думаю не надо делать, тс наверняка справится с редиректом оутпута в файл
 
Если у него это сутками работает, то возьмем, что мы отправляем 4 запроса в секунду, это 345600 запросов в сутки. Это подписка за 300 баксов.
код берет с etherscan только Abi которые нужны для декодирования поля data в транзакции, если напарсить локально abi и взять wss rpc от quicknode то скорость будет на уровне и без подписок за сотни баксов
бесплатной апишки blockcypher тоже будет достаточно так как она используется редко
основная нагрузка на rpc
 
Последнее редактирование:
Нужно написать простенький парсер по езерскану.
Суть работы следующая: У меня имеется список адресов, среди всей массы этих адресов мне нужно выделить те адреса - у которых в истории транз имеется нужна мне транзакция. На скрине выделил какой столбец нужно парсить, к примеру мне нужны все адреса которые имеют транзакцию "Execute"
Я прописываю этот самый "Execute" в качестве переменной для поиска и парсер начинает в каждом адресе искать транзакцию с таким именем, если находит-сохраняем этот адрес в блокнотик, если нет переходим к следующему адресу. Суть думаю вы поняли.
Главный нюанс это скорость работы софта, хотелось бы добиться минимум 20-30 адресов в секунду и без прокси) такое реально?
Отказ от прокси обосновываю дороговизной чека, есть аналогичный софт у меня - не успеваю пополнять балансы в прокси сервисах.
Возможно минуя etherscan эти данные можно вытащить с паблик нод...
Если у кого есть идеи по реализации и готов взяться за работу-прошу в пм
Посмотреть вложение 70647
del
 
Последнее редактирование:
А почему нельзя скачать блокчейн и оффлайн распарсить? Зачем апи и эфирсканы?
Сможешь помочь в реализации?
Mне не принципиально через езерсканы, ноды или апи.
Мне подойдет любой способ который справится с моей задачей. Главные критерии-дешевизна и скорость работы.
 
Сможешь помочь в реализации?
Mне не принципиально через езерсканы, ноды или апи.
Мне подойдет любой способ который справится с моей задачей. Главные критерии-дешевизна и скорость работы.
Я не разработчик, просто блокчейн - "децентрализованная БД". Зачем парсить эту БД находящуюся на чьихто серверах, если можно скачать? (если я не прав, просьба пояснить).
 
Я не разработчик, просто блокчейн - "децентрализованная БД". Зачем парсить эту БД находящуюся на чьихто серверах, если можно скачать? (если я не прав, просьба пояснить).
Да еще и используя api и реквесты к rpc, когда локальная бд вот она, скорость намного выше...
 
да, вы правы но тут с нюансами, для эфира например блокчейн весит 850 гб
для bsc под 3 тб
нужен хороший ssd с хорошей скоростью на такой обьем и хороший пк чтобы мог быстро лопатить этот блокчейн
еще оно будет импортировать неизвестно сколько времени даже если скачать этот блокчейн raw и запустить синхронизацию
 
При
требует доработки
использование
установить python3, установить pip, установить зависимости
вставить в код апи ключ etherscan, зарегистрироватся на quicknode, создать eth endpoint, взять websocket url и вставить в код
pip3 install requests web3 colorlog
python3 script.py "C:\wallets.txt" "swap,execute"
файл abis.json будет походу работы заполятся и запросов к etherscan будет все меньше и меньше

Python:
import requests
import logging
from colorlog import ColoredFormatter
from web3 import Web3
import json
import sys
import os

formatter = ColoredFormatter(
    # %(asctime)s - %(name)s - %(levelname)s - %(message)s
    "%(log_color)s%(asctime)s-%(levelname)-5s%(reset)s %(blue)s%(message)s",
    datefmt=None,
    reset=True,
    log_colors={
        'DEBUG':    'cyan',
        'INFO':     'green',
        'WARNING':  'yellow',
        'ERROR':    'red',
        'CRITICAL': 'red,bg_white',
    },
    secondary_log_colors={},
    style='%'
)
logger = logging.getLogger('')
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)

#paste here etherscan api key
ETHERSCAN_API_KEY = ""

#paste here quicknode eth wss endpoint url
#http://sample-endpoint-name.network.quiknode.pro/token-goes-here/
quickNodeWssUrl = ""

abis_cache = {}
if os.path.isfile("abis.json"):
    with open('abis.json') as f:
        abis_cache = json.load(f)
addrs = []
if len(sys.argv) < 3:
    logger.error("need wallets file as fist arg")
    logger.error("need method list as second arg")
    logger.info('ex: script.py "C:\wallets.txt" "swap,execute"')
    quit()

wallets_file = sys.argv[1]
if os.path.isfile(wallets_file):
    with open(wallets_file) as f:
        addrs = f.read().splitlines()
else:
    logger.error("need wallets file as fist arg")
    logger.info('ex: script.py "C:\wallets.txt" "swap,execute"')
    quit()

fn_names = sys.argv[2].lower().strip().split(",") 
is_Connected = False
try:
    if len(quickNodeWssUrl) == 0:
        w3 = Web3(Web3.HTTPProvider("https://rpc.builder0x69.io"))
    else:
        w3 = Web3(Web3.WebsocketProvider(quickNodeWssUrl))
    is_Connected = w3.is_connected()
    logging.info("Connected: "+str(is_Connected))
except Exception as e:
    logger.exception(e)
    quit()

def check_address(addr, types):
    txs = json.loads(requests.get(
        f"https://api.blockcypher.com/v1/eth/main/addrs/{addr}").text)
    if "txrefs" not in txs:
        logger.error("BlockCypher api error")
        return
    for item in txs["txrefs"]:
        tx = w3.eth.get_transaction(item["tx_hash"])
        input = tx["input"]
        if len(input) == 0:
            name = 'transfer'
        else:
            if tx['to'] in abis_cache:
                abi = abis_cache[tx['to']]
            else:
                abi_endpoint = f"https://api.etherscan.io/api?module=contract&action=getabi&address={tx['to']}&apikey={ETHERSCAN_API_KEY}"
                abi = json.loads(requests.get(abi_endpoint).text)
                if abi["message"] == "OK":
                    abi = abi['result']
                    abis_cache[tx['to']] = abi
                else:
                    logger.error("receive abi error: "+abi['result'])
                    continue
            contract = w3.eth.contract(Web3.to_checksum_address(
                tx["to"]), abi=abi, decode_tuples=True)
            function_signature, arguments = contract.decode_function_input(input)
            name = function_signature.fn_name.lower()
        if name in fn_names:
            logger.info(f"{addr} found {name}")
            return

for item in addrs:
    check_address(item, fn_names)
with open("abis.json", "w") as f:
    f.write(json.dumps(abis_cache, indent=4))
Привет, ты когдато работал с смарт контрактами и web3 приложениями? С Дексами и знаком с мев стратегиям ликвид фермамии и блокчейн разработкой? Если да, то отпиши в лс или в месенджере (указаны в профиле)
 
я так понял, что тсу нужно именно парсить, а не через апи.
Если у него это сутками работает, то возьмем, что мы отправляем 4 запроса в секунду, это 345600 запросов в сутки. Это подписка за 300 баксов.

Тс, что дороже прокси или подписка?
Может тебе стоит через подписку делать?



а че адреса не спарсил?


C++:
#include <iostream>
#include <string>
#include <vector>

#define CURL_STATICLIB
#include <curl/curl.h>

using namespace std;

#ifdef _DEBUG
#pragma comment(lib, "libcurl_a_debug.lib")
#else
#pragma comment(lib, "libcurl_a.lib")
#endif

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "normaliz.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "wldap32.lib")

size_t writefunc(void* ptr, size_t size, size_t nmemb, string* s) {
    string data(reinterpret_cast<const char*>(ptr), size * nmemb);
    *s += data;
    return size * nmemb;
}

using wallets_list = vector<string>;

wallets_list parse_page_wallets(string content, const string& method_name) {
    wallets_list result;
    const string to_find = "title=\"" + method_name + "\">" + method_name;
    size_t pos = content.find(to_find);

    while (pos != -1) {
        content = content.substr(pos);
        pos = content.find(" data-bs-title=\"0x"); // не предусмотрен парсинг кошельков бирж
        content = content.substr(pos + 16);
        string wallet = content.substr(0, content.find("\">"));
        if (wallet.size() >= 40 && wallet.size() <= 44)
            result.push_back(move(wallet));
        pos = content.find(to_find);
    }

    return result;
}


int main(int argc, char* argv[]) {
    const string trans_method = "Execute"; // метод, который надо парсить
    const string start_page = "https://etherscan.io/txs?ps=100&p=";
    const char useragent[] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36";

    CURL* curl = nullptr;
    CURLcode res;
 
    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();

    if (curl) {
        for (int i = 1; i <= 5000; ++i) {
            string page = start_page + to_string(i);
            string result = "";

            curl_easy_setopt(curl, CURLOPT_URL, page.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
            curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent);
            res = curl_easy_perform(curl);

            if (res) {
                cerr << "something went wrong!" << endl;
                break;
            }

            wallets_list wallets = parse_page_wallets(move(result), trans_method);
            for (const auto& wallet : wallets)
                cout << wallet << endl;
        }
        curl_easy_cleanup(curl);
    }
    else {
        cerr << "libcurl init failed" << endl;
    }

    curl_global_cleanup();
    return 0;
}
накидал за 20 мин, если кому не впадлу, то допилите сюда прокси и проверку этих самых прокси :))
ну и выплюньте тсу
сохранение в файл, думаю не надо делать, тс наверняка справится с редиректом оутпута в файл
Привет я ищу талантливых кодеров (ответ выше), чтоб не спамить.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх