Парсинг данных о криптовалютах: От простого к сложному
Криптовалюты — это динамичный мир, где данные меняются ежеминутно. Парсинг помогает трейдерам и аналитикам извлекать ценную информацию из API, веб-сайтов и файлов. В этой статье мы разберём парсинг от простого к сложному: начнём с разбора строк и JSON, перейдём к XML и CSV, а закончим веб-скрейпингом HTML с использованием Python.
1. Введение в парсинг: Почему это важно для крипты?
Парсинг — это процесс извлечения структурированных данных из неструктурированного или полуструктурированного источника. В криптовалютах данные приходят из API (CoinMarketCap), веб-сайтов (CoinGecko) или логов транзакций. Без парсинга это займёт часы ручной работы, с парсингом — секунды автоматизации.
Предварительные требования: Установите Python 3 и библиотеки:
pip install requests beautifulsoup4 lxml
2. Простой парсинг: Разбор строк
Начнём с простого. Допустим, у вас есть строка: «Bitcoin: 45000 USD, Ethereum: 3000 USD».
Пример 1: Парсинг строки с помощью split()
data_string = "Bitcoin: 45000 USD, Ethereum: 3000 USD"
# Разделяем строку по запятой, затем по двоеточию
parts = data_string.split(", ")
btc_info = parts[0].split(": ")
eth_info = parts[1].split(": ")
btc_name = btc_info[0]
btc_price = int(btc_info[1].split(" ")[0])
eth_name = eth_info[0]
eth_price = int(eth_info[1].split(" ")[0])
print(f"{btc_name} цена: {btc_price} USD")
print(f"{eth_name} цена: {eth_price} USD")
Что делает код: Делит строку по запятой и двоеточию, извлекает названия и цены, преобразует цены в числа. Это простой метод для логов транзакций.
Результат:
3. Парсинг JSON: Данные из API
JSON — стандарт для API криптобирж. Используем CoinGecko API для получения цен.
Пример 2: Парсинг JSON
import requests
import json
url = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd"
response = requests.get(url)
if response.status_code == 200:
data = json.loads(response.text)
btc_price = data['bitcoin']['usd']
eth_price = data['ethereum']['usd']
print(f"Bitcoin: {btc_price} USD")
print(f"Ethereum: {eth_price} USD")
else:
print("Ошибка запроса")
Что делает код: Запрашивает JSON, преобразует его в словарь, извлекает цены. Проверка status_code предотвращает сбои. Полезно для трейдинг-ботов.
Результат:
4. Парсинг XML: Для специфических источников
XML используется в RSS-фидах (например, CoinDesk). Пример XML:
<cryptonews>
<item>
<title>Bitcoin растёт</title>
<price>45000</price>
</item>
<item>
<title>Ethereum обновление</title>
<price>3000</price>
</item>
</cryptonews>
Пример 3: Парсинг XML с ElementTree
import xml.etree.ElementTree as ET
xml_data = """
<cryptonews>
<item>
<title>Bitcoin растёт</title>
<price>45000</price>
</item>
<item>
<title>Ethereum обновление</title>
<price>3000</price>
</item>
</cryptonews>
"""
root = ET.fromstring(xml_data)
for item in root.findall('item'):
title = item.find('title').text
price = int(item.find('price').text)
print(f"Новость: {title}, Цена: {price} USD")
Что делает код: Парсит XML в дерево, извлекает заголовки и цены. Полезно для новостных фидов.
5. Парсинг CSV: Анализ транзакций
CSV — формат для экспорта данных с бирж. Пример: «coin,price,date».
Пример 4.0: Получение цен валют и сохранение в CSV
import requests
import csv
from datetime import datetime
url = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open('crypto_prices.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['coin', 'price', 'timestamp'])
writer.writerow(['Bitcoin', data['bitcoin']['usd'], timestamp])
writer.writerow(['Ethereum', data['ethereum']['usd'], timestamp])
print("Данные сохранены в crypto_prices.csv")
else:
print("Ошибка запроса")
Что делает код: Запрашивает цены Bitcoin и Ethereum через API CoinGecko, сохраняет их в CSV-файл с временной меткой.
Результат:
Пример 4.1: Извлечение данных из CSV
import csv
with open('crypto_prices.csv', 'r') as f:
reader = csv.DictReader(f)
for row in reader:
coin = row['coin']
price = float(row['price'])
timestamp = row['timestamp']
print(f"{coin}: {price} USD на {timestamp}")
Что делает код: Читает CSV-файл, созданный в примере 4.1, и выводит данные о монетах, ценах и времени.
Результат:
6. Продвинутый парсинг: Веб-скрейпинг
Скрейпинг CoinMarketCap для топ-крипты с BeautifulSoup.
Пример 5: Базовый скрейпинг
import requests
from bs4 import BeautifulSoup
url = "https://coinmarketcap.com/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
table = soup.find('table', class_='cmc-table')
rows = table.find_all('tr')[1:3]
for row in rows:
cols = row.find_all('td')
name = cols[1].text.strip()
price = cols[3].text.strip()
print(f"{name}: {price}")
Что делает код: Извлекает имена и цены из таблицы. Уважайте robots.txt!
Результат:
Пример 6: Продвинутый парсинг
Пример 6 демонстрирует продвинутый веб-парсинг данных о криптовалютах с сайта CoinMarketCap (https://coinmarketcap.com/) с использованием библиотек Python requests и BeautifulSoup. Код извлекает названия, тикеры и цены криптовалют из таблицы на двух страницах сайта, обрабатывает возможные ошибки, использует CSS-селекторы для точного парсинга. Основная цель — получить структурированные данные (название, тикер и цена) для первых пяти монет с каждой страницы и вывести их в консоль.
Основные особенности
- Пагинация: Код обрабатывает две страницы (
?page=1и?page=2), чтобы извлечь данные из разных частей рейтинга. по 5 монет из каждой страницы. - Обработка ошибок: Проверяет HTTP-ошибки и отсутствие таблицы.
- Этичный скрейпинг: Задержка в 2 секунды между запросами снижает нагрузку на сервер.
- CSS-селекторы: Использует точные селекторы для извлечения данных из HTML.
- Ограничение вывода: Извлекает только первые 5 монет с каждой страницы для упрощения.
Код
import requests
from bs4 import BeautifulSoup
import time
def scrape_page(page_num):
url = f"https://coinmarketcap.com/?page={page_num}"
try:
response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Ошибка: {e}")
return []
soup = BeautifulSoup(response.text, 'lxml')
table = soup.select_one('table')
if not table:
print("Таблица не найдена")
return []
data = []
for index, row in enumerate(table.select('tbody tr')[0:5], 1): # Первые 5 монет
name_cell = row.select_one('p.sc-65e7f566-0.iPbTJf.coin-item-name')
ticker_cell = row.select_one('td:nth-child(2) span.sc-65e7f566-0')
price_cell = row.select_one('td:nth-child(4) span')
name = name_cell.text.strip() if name_cell else "N/A"
ticker = ticker_cell.text.strip() if ticker_cell else ""
price = price_cell.text.strip() if price_cell else "N/A"
full_name = f"{name} {ticker}".strip()
print(f"{index}: {full_name} - {price}")
data.append((full_name, price))
return data
all_data = []
for page in range(1, 3):
all_data.extend(scrape_page(page))
time.sleep(2)
print("\nИтоговые данные:")
for index, (name, price) in enumerate(all_data, 1):
print(f"{index}: {name} - {price}")
Результат:
Пошаговое объяснение кода
Импорт библиотек
import requests
from bs4 import BeautifulSoup
import time
requests: Для отправки HTTP-запросов к сайту.BeautifulSoup(изbs4): Для парсинга HTML и извлечения данных.time: Для добавления задержки между запросами.
Функция scrape_page(page_num)
def scrape_page(page_num):
url = f"https://coinmarketcap.com/?page={page_num}"
try:
response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Ошибка: {e}")
return []
- Назначение: Принимает номер страницы и извлекает данные о криптовалютах.
- URL: Формирует URL для конкретной страницы (например,
?page=1). - HTTP-запрос: Отправляет GET-запрос с таймаутом 10 секунд и User-Agent для имитации браузера.
- Обработка ошибок: Проверяет успешность запроса; при ошибке (например, 404) возвращает пустой список.
Парсинг HTML
soup = BeautifulSoup(response.text, 'lxml')
table = soup.select_one('table')
if not table:
print("Таблица не найдена")
return []
BeautifulSoup(response.text, 'lxml'): Парсит HTML с парсеромlxml(быстрее стандартного).soup.select_one('table'): Находит первый тег<table>с данными.- Если таблица не найдена, возвращается пустой список.
Извлечение данных
data = []
for index, row in enumerate(table.select('tbody tr')[0:5], 1): # Первые 5 монет
name_cell = row.select_one('p.sc-65e7f566-0.iPbTJf.coin-item-name')
ticker_cell = row.select_one('td:nth-child(2) span.sc-65e7f566-0')
price_cell = row.select_one('td:nth-child(4) span')
name = name_cell.text.strip() if name_cell else "N/A"
ticker = ticker_cell.text.strip() if ticker_cell else ""
price = price_cell.text.strip() if price_cell else "N/A"
full_name = f"{name} {ticker}".strip()
print(f"{index}: {full_name} - {price}")
data.append((full_name, price))
return data
- Инициализация: Создаётся список
dataдля хранения пар (название+тикер, цена). - Цикл: Перебирает первые 5 строк таблицы (
tbody tr[0:5]), нумеруя с 1. - Извлечение:
- Имя:
p.sc-65e7f566-0.iPbTJf.coin-item-nameизвлекает название (например, «Bitcoin»). - Тикер:
td:nth-child(2) span.sc-65e7f566-0пытается извлечь тикер (например, «BTC»). - Цена:
td:nth-child(4) spanизвлекает цену (например, «$115,407.32»).
- Имя:
- Обработка: Если элемент не найден, возвращается «N/A» или пустая строка. Имя и тикер объединяются в
full_name. - Вывод: Печатает строку вида
1: Bitcoin BTC - $115,407.32и добавляет данные вdata. - Возврат: Возвращает список
data.
Сбор данных с нескольких страниц
all_data = []
for page in range(1, 3):
all_data.extend(scrape_page(page))
time.sleep(2)
all_data: Список для хранения данных со всех страниц.- Цикл: Перебирает страницы 1 и 2, вызывая
scrape_page. extend: Добавляет данные страницы вall_data.time.sleep(2): Задержка 2 секунды для этичности.
Итоговый вывод
print("\nИтоговые данные:")
for index, (name, price) in enumerate(all_data, 1):
print(f"{index}: {name} - {price}")
- Выводит заголовок и все данные из
all_dataв формате1: Bitcoin BTC - $115,407.32.
Проблемы и рекомендации
Ограничение: Код извлекает только 5 монет на страницу ([0:5]). Для большего количества измените на [0:10].
API: Для надёжности используйте API CoinMarketCap (https://coinmarketcap.com/api/).
Антибот-защита: Если сайт блокирует, добавьте заголовки:
headers = {
'User-Agent': 'Mozilla/5.0',
'Accept': 'text/html',
'Accept-Language': 'en-US,en;q=0.9'
}
7. Заключение
Мы прошли от split() до скрейпинга с BeautifulSoup. Парсинг криптоданных открывает путь к торговым ботам и анализу. Экспериментируйте с базами данных или asyncio.
Смотрите примеры и изучайте уроки на https://parsertools.ru
