-
-
Save sashaboulouds/d6cf5e034e2a505c2337a26e76cf2a83 to your computer and use it in GitHub Desktop.
| # ============================================================================= | |
| # Title: DexScreener Crypto Live Prices Scraper | |
| # Description: This script scrape the first 200 h6 trending Solana pairs from DexScreener β every 10 seconds | |
| # Author: Sasha Bouloudnine | |
| # Date: 2024-03-13 | |
| # | |
| # Usage: | |
| # - Install websocket using `pip install websockets`. | |
| # - Launch the script. | |
| # | |
| # ============================================================================= | |
| import asyncio | |
| import websockets | |
| from datetime import datetime | |
| import os | |
| import base64 | |
| import json | |
| import csv | |
| import time | |
| def generate_sec_websocket_key(): | |
| random_bytes = os.urandom(16) | |
| key = base64.b64encode(random_bytes).decode('utf-8') | |
| return key | |
| TYPES = ['pairs', 'latestBlock'] | |
| DATA = [] | |
| FIELDNAMES = [ | |
| "chain_id", | |
| "dex_id", | |
| "pair_address", | |
| "token_address", | |
| "token_name", | |
| "token_symbol", | |
| "token_m5_buys", | |
| "token_m5_sells", | |
| "token_h1_buys", | |
| "token_h1_sells", | |
| "token_h1_to_m5_buys", | |
| "token_liquidity", | |
| "token_market_cap", | |
| "token_created_at", | |
| "token_created_since", | |
| "token_eti", | |
| "token_header", | |
| "token_website", | |
| "token_twitter", | |
| "token_links", | |
| "token_img_key", | |
| "token_price_usd", | |
| "token_price_change_h24", | |
| "token_price_change_h6", | |
| "token_price_change_h1", | |
| "token_price_change_m5" | |
| ] | |
| async def dexscreener_scraper(): | |
| headers = { | |
| "Host": "io.dexscreener.com", | |
| "Connection": "Upgrade", | |
| "Pragma": "no-cache", | |
| "Cache-Control": "no-cache", | |
| "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", | |
| "Upgrade": "websocket", | |
| "Origin": "https://dexscreener.com", | |
| "Sec-WebSocket-Version": 13, | |
| "Accept-Encoding": "gzip, deflate, br, zstd", | |
| "Accept-Language": "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7", | |
| "Sec-WebSocket-Key": generate_sec_websocket_key() | |
| } | |
| uri = "wss://io.dexscreener.com/dex/screener/pairs/h24/1?rankBy[key]=trendingScoreH6&rankBy[order]=desc" | |
| async with websockets.connect(uri, extra_headers=headers) as websocket: | |
| while True: | |
| message_raw = await websocket.recv() | |
| message = json.loads(message_raw) | |
| _type = message["type"] | |
| assert _type in TYPES | |
| if _type == 'pairs': | |
| pairs = message["pairs"] | |
| assert pairs | |
| for pair in pairs: | |
| chain_id = pair["chainId"] | |
| dex_id = pair["dexId"] | |
| pair_address = pair["pairAddress"] | |
| assert pair_address | |
| token_address = pair["baseToken"]["address"] | |
| token_name = pair["baseToken"]["name"] | |
| token_symbol = pair["baseToken"]["symbol"] | |
| token_txns = pair["txns"] | |
| token_m5_buys = token_txns["m5"]["buys"] | |
| token_m5_sells = token_txns["m5"]["sells"] | |
| token_h1_buys = token_txns["h1"]["buys"] | |
| token_h1_sells = token_txns["h1"]["sells"] | |
| token_h1_to_m5_buys = round(token_m5_buys*12/token_h1_buys, 2) if token_m5_buys else None | |
| token_liquidity = pair["liquidity"]["usd"] | |
| token_market_cap = pair["marketCap"] | |
| token_created_at_raw = pair["pairCreatedAt"] | |
| token_created_at = token_created_at_raw / 1000 | |
| token_created_at = datetime.utcfromtimestamp(token_created_at) | |
| now_utc = datetime.utcnow() | |
| token_created_since = round((now_utc - token_created_at).total_seconds() / 60, 2) | |
| token_eti = pair.get("eti", False) | |
| token_header = pair.get("profile", {}).get("header", False) | |
| token_website = pair.get("profile", {}).get("website", False) | |
| token_twitter = pair.get("profile", {}).get("twitter", False) | |
| token_links = pair.get("profile", {}).get("linkCount", False) | |
| token_img_key = pair.get("profile", {}).get("imgKey", False) | |
| token_price_usd = pair["priceUsd"] | |
| token_price_change_h24 = pair["priceChange"]["h24"] | |
| token_price_change_h6 = pair["priceChange"]["h6"] | |
| token_price_change_h1 = pair["priceChange"]["h1"] | |
| token_price_change_m5 = pair["priceChange"]["m5"] | |
| VALUES = [ | |
| chain_id, | |
| dex_id, | |
| pair_address, | |
| token_address, | |
| token_name, | |
| token_symbol, | |
| token_m5_buys, | |
| token_m5_sells, | |
| token_h1_buys, | |
| token_h1_sells, | |
| token_h1_to_m5_buys, | |
| token_liquidity, | |
| token_market_cap, | |
| token_created_at, | |
| token_created_since, | |
| token_eti, | |
| token_header, | |
| token_website, | |
| token_twitter, | |
| token_links, | |
| token_img_key, | |
| token_price_usd, | |
| token_price_change_h24, | |
| token_price_change_h6, | |
| token_price_change_h1, | |
| token_price_change_m5 | |
| ] | |
| print(token_name, token_price_usd) | |
| row = dict(zip(FIELDNAMES, VALUES)) | |
| DATA.append(row) | |
| file_created_at = int(time.time()) | |
| filename = 'dexscreener_%s.csv' % file_created_at | |
| with open(filename, 'w') as f: | |
| writer = csv.DictWriter(f, fieldnames=FIELDNAMES, delimiter='\t') | |
| writer.writeheader() | |
| for row in DATA: | |
| writer.writerow(row) | |
| print('done %s' % filename) | |
| print('pause 10s :Β°') | |
| time.sleep(10) | |
| if __name__ == "__main__": | |
| asyncio.run(dexscreener_scraper()) |
Here is an example map for a pair and the data I have working:
b'\x0csolana\x0eraydium\x00XFEeo6Hof4tLCTcgbwCeJru4veVRHnXpRYzdA3accFrE3X74ZnBs4M4q2icYPLKry6RDFhCEKwgYNZAqq5Hxjkpump\x08goob\x08goob\x02\x00\x00\x00\x00\x00\x00\x18@\x00VSo11111111111111111111111111111111111111112\x16Wrapped SOL\x06SOL\x02\x00\x00\x00\x00\x00\x00"@\x06SOL\x160.000001964\x02\x120.0004781\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00$@\x00\x00\x00\x00\x00\x00(@\x00\x00\x00\x00\x00\xc0W@\x00\x00\x00\x00\x00\x00Q@\x00\x00\x00\x00\x00\xb0}@\x00\x00\x00\x00\x00@w@\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x80Q@\x00\x00\x00\x00\x00`p@\x02\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x80I@\x00\x00\x00\x00\x00@n@\x02\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x000@\x00\x00\x00\x00\x00\x00W@\x00\x00\x00\x00\x00\x90u@\x02\xecQ\xb8\x1e\x85\x1be@\x023333\xb3M\xab@\x02\xcd\xcc\xcc\xcct\xfc\xf0@\x02\x85\xebQ\xb8j\xfa\x0bA\x02\x00\x02\xa4p=\n\xd7=\x8f@\x02\x00\x00\x00\x00\xd8#\xe1@\x02\x1f\x85\xebQ\xd4\x8c\xfb@\x02\x02\xecQ\xb8\x1e\x85\x1be@\x02\x1f\x85\xebQ8~\xa3@\x02{\x14\xaeG\x11\xd5\xe0@\x02\\\x8f\xc2\xf5\x00h\xfc@\x02\xe1z\x14\xaeG\xe1\xca\xbf\x02\x00\x00\x00\x00\x00\x00\x12\xc0\x02\x1f\x85\xebQ\xb8\x1e\t@\x02\xecQ\xb8\x1e\x85k \xc0\x02H\xe1z\x14\x8e\xcf\xfc@\x00\x00\x00$\xbdl\x9dA\xca\xc3B\xadiJn@\x02\x00\x00\x00\x00\xf8\x1e\x1bA\x02\x00\x00\x00\x00\xf8\x1e\x1bA\x02\x00\x00\xf2\xb8\xd62yB\x02\x01\x02\x01\x02\x01\x00\x02\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00@\x02\x0caa65ec\x00\x01\x00\x02a\x0csolamm\x02\x00\x00'
{'chainId': 'solana', 'dexId': 'raydium', 'labels': [], 'pairAddress': 'ChUNGiiC4LjHRXY1rHi8y2pGTDumyfQaEiMSdjhF8xu2', 'baseToken': {'address': 'Gg7yp9ZL4Fszk26zPmVToCvEqSXWLRR25KsgKQdFpump', 'name': 'SOL RACCOON', 'symbol': 'RACCOON', 'decimals': 6}, 'quoteToken': {'address': 'So11111111111111111111111111111111111111112', 'name': 'Wrapped SOL', 'symbol': 'SOL', 'decimals': 9}, 'quoteSymbol': 'SOL', 'price': '0.000003900', 'priceUsd': '0.0009495', 'txns': {'m5': {'buys': 92, 'sells': 79}, 'h1': {'buys': 1649, 'sells': 1248}, 'h6': {'buys': 16066, 'sells': 14433}, 'h24': {'buys': 49388, 'sells': 33272}}, 'buyers': {'m5': 81, 'h1': 1224, 'h6': 12333, 'h24': 37374}, 'sellers': {'m5': 68, 'h1': 899, 'h6': 8995, 'h24': 14724}, 'makers': {'m5': 124, 'h1': 1714, 'h6': 17118, 'h24': 38718}, 'volume': {'m5': 23324.79, 'h1': 401164.58, 'h6': 6699571.2, 'h24': 16246400.3}, 'volumeBuy': {'m5': 10799.88, 'h1': 203351.66, 'h6': 3335607.43, 'h24': 8151975.68}, 'volumeSell': {'m5': 12524.91, 'h1': 197812.91, 'h6': 3363963.76, 'h24': 8094424.61}, 'priceChange': {'m5': -3.93, 'h1': 15.67, 'h6': -54.4, 'h24': 424.0}, 'liquidity': {'usd': 152295.23, 'base': 80279977.0, 'quote': 312.4312}, 'marketCap': 949560, 'fdv': 949560, 'pairCreatedAt': 1732712673000}
did anyone found solution?
b'\n1.3.0\x08pair\x02\x0csolana\x0eraydium\x00X83G6VzJzLRCnHBsLATj94VCpRimyyqwuN6ZfL11McADLXGtDZKAqvMZMnti46ZewMiXCa4oXF4bZxwQPoKzXPFxZn\x0cnubcat\x06nub\x02\x00\x00\x00\x00\x00\x00"@\x00VSo11111111111111111111111111111111111111112\x16Wrapped SOL\x06SOL\x02\x00\x00\x00\x00\x00\x00"@\x06SOL\x140.00008376\x02\x0e0.02034\x00\x00\x00\x00\x00\x00.@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\xc0R@\x00\x00\x00\x00\x00\x00M@\x00\x00\x00\x00\x00\x10u@\x00\x00\x00\x00\x00\xc0u@\x00\x00\x00\x00\x00\xf8\x92@\x00\x00\x00\x00\x00<\x92@\x02\x00\x00\x00\x00\x00\x00*@\x00\x00\x00\x00\x00\x00M@\x00\x00\x00\x00\x00\xe0h@\x00\x00\x00\x00\x00\xf0\x82@\x02\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00J@\x00\x00\x00\x00\x00\xe0i@\x00\x00\x00\x00\x00\x88\x81@\x02\x00\x00\x00\x00\x00\x002@\x00\x00\x00\x00\x00@Y@\x00\x00\x00\x00\x00pu@\x00\x00\x00\x00\x00\xd0\x8d@\x02\xe1z\x14\xaeg\xec\xce@\x02\n\xd7\xa3p\xfd\x0f\xf7@\x02H\xe1z\x14+^\x13A\x02\n\xd7\xa30#g2A\x02\x02\n\xd7\xa3p=\xc2\xa8@\x02\xa4p=\n\x97\xcb\xe3@\x02\xa4p=\n#\x08\x02A\x02\xaeG\xe1z\xe7/"A\x02\x02\x1f\x85\xebQ\xd8\xbb\xc8@\x02R\xb8\x1e\x85cT\xea@\x02\xecQ\xb8\x1e3\xb4\x04A\x02\x14\xaeG\xe1^\x9e"A\x02H\xe1z\x14\xaeG\xfd\xbf\x02\x8f\xc2\xf5(\\\x8f\xe2\xbf\x02H\xe1z\x14\xaeG\x1f\xc0\x02\x85\xebQ\xb8\x1e\x85\r\xc0\x02\xe1z\x14\xce\x92=BA\x00\x00\x00\xa0\x17\x0e\x8cAH\xe1z\x14\xee4\xb3@\x02\x00\x00\x00\xb0\xfdesA\x02\x00\x00\x00\xb0\xfdesA\x02\x00\x80\xa4\x9f6\xe7xB\x02\x01\x02\x01\x0'
for this encoding?
@prodpeak , Hi, how can i contact you regarding your work?
@prodpeak , Hi, how can i contact you regarding your work?
Share your telegram username and I'll DM you
Hi, how can i contact you regarding your work?
I have been looking for an answer to this problem for a long time
v4
now that's doesn't work:')
@prodpeak hi sir please how can i joind you on telegram
@prodpeak heya, I wanna checkout your code, tele is https://t.me/stevegremory
Hi @prodpeak , were you able to find a solution to this. can i please have a look at the code my telegram is https://t.me/kratkrish
Hi, how can i contact you regarding your work?
@BOTtellegrams
I have been looking for an answer to this problem for a long time
OK. I've done it (sort of).
I worked through the data structure and manually mapped the data out of the binary format into a readable JSON format.
It's a bit messy when I get down to the links and making adjustments for tokens that are launched on moonshot, but it works.
I won't share the code here, but HMU if you want to review my work and continue to build on it.
There is a stats section at the beginning of the binary data for global tx volume. After that each token follows this format:
Tokens are static for all fields before and including pairCreatedAt.
After that they differ depending on token type, launchpad, etc. I've not fully mapped those fields.