{"id":24067843,"url":"https://github.com/alexandrecpedro/coinbaseapi_extract_etl","last_synced_at":"2026-05-04T10:32:31.134Z","repository":{"id":271548013,"uuid":"913808329","full_name":"alexandrecpedro/CoinBaseAPI_Extract_ETL","owner":"alexandrecpedro","description":"ETL complete project with Python with Dashboard","archived":false,"fork":false,"pushed_at":"2025-01-08T12:19:50.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-08T12:38:24.423Z","etag":null,"topics":["bitcoin","coinbase-api","logfire","postgresql","python","render","streamlit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexandrecpedro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-08T11:47:51.000Z","updated_at":"2025-01-08T12:19:53.000Z","dependencies_parsed_at":"2025-01-08T12:38:33.868Z","dependency_job_id":"e8d480ea-2ee7-4446-ab4e-810b1496f1ba","html_url":"https://github.com/alexandrecpedro/CoinBaseAPI_Extract_ETL","commit_stats":null,"previous_names":["alexandrecpedro/coinbaseapi_extract_etl"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrecpedro%2FCoinBaseAPI_Extract_ETL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrecpedro%2FCoinBaseAPI_Extract_ETL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrecpedro%2FCoinBaseAPI_Extract_ETL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrecpedro%2FCoinBaseAPI_Extract_ETL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexandrecpedro","download_url":"https://codeload.github.com/alexandrecpedro/CoinBaseAPI_Extract_ETL/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240926393,"owners_count":19879738,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","coinbase-api","logfire","postgresql","python","render","streamlit"],"created_at":"2025-01-09T12:39:12.629Z","updated_at":"2026-05-04T10:32:31.072Z","avatar_url":"https://github.com/alexandrecpedro.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":" \n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://suajornadadedados.com.br/\"\u003e\u003cimg src=\"https://github.com/lvgalvao/data-engineering-roadmap/raw/main/pics/logo.png\" alt=\"Jornada de Dados\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003eNossa missão é fornecer o melhor ensino em engenharia de dados\u003c/em\u003e\n\u003c/p\u003e\n\nBem-vindo a **Jornada de Dados**\n\n# Extração de API do zero - Projeto completo de ETL com Python e Microsoft Azure, até o Dashboard.\nAqui está o **README** atualizado, agora usando a **API da Bitcoin na Coinbase** como referência:\n\n---\n\nEsquema do projeto: [app.excalidraw.com](https://app.excalidraw.com/s/8pvW6zbNUnD/9zZctm3OR9f)\n\n---\n\n# 💰 **Data Pipeline: Extração de Dados Bitcoin com ETL em Python**  \n\n\u003cimg width=\"1604\" alt=\"Extração de Dados Bitcoin com ETL em Python\" src=\"./assets/images/project.png\"\u003e\n\n## **Introdução**  \n\nEste projeto faz parte de um workshop gratuito de **Data Engineering para Iniciantes**, focado na criação de pipelines de dados ETL (Extract, Transform, Load). O objetivo é construir um programa que consome dados de uma **API** (Coinbase), organiza esses dados e armazena em uma base de dados.  \n\nVocê aprenderá conceitos fundamentais de Engenharia de Dados, como:  \n1. O que é uma API e como consumi-la usando Python.  \n2. O processo completo de ETL (extração, transformação e carga).  \n3. Como automatizar a execução do pipeline para coleta contínua.  \n\nAo final do projeto, você terá um programa funcional que:  \n- Coleta o preço atual da Bitcoin em tempo real.  \n- Salva esses dados em um formato tabular para futura análise.  \n\n---\n\n## **Overview do Projeto**  \n\n### **Objetivo Principal**  \nDesenvolver um pipeline ETL automatizado para consumir dados da **API da Coinbase** e armazenar informações sobre o preço da Bitcoin ao longo do tempo.  \n\n### **Etapas do Projeto**  \n\n1. **Extração (E)**:  \n   - Utilizar a **API da Coinbase** para obter o preço atual da Bitcoin.  \n   - Trabalhar com os endpoints públicos da API (sem necessidade de autenticação).  \n\n2. **Transformação (T)**:  \n   - Selecionar apenas as informações relevantes: preço da Bitcoin, horário da consulta e moeda de referência (USD).  \n   - Organizar os dados no formato tabular utilizando **Pandas**.  \n\n3. **Carga (L)**:  \n   - Armazenar os dados coletados em um arquivo **CSV** ou em um banco de dados SQLite.  \n\n4. **Automatização**:  \n   - Agendar o programa para executar periodicamente (por exemplo, a cada hora ou diariamente), garantindo a coleta contínua dos dados.  \n\n---\n\n## **Tecnologias Utilizadas**  \n- **Python 3.12**  \n- **Bibliotecas**:  \n   - `requests`: Para consumir APIs.  \n   - `pandas`: Para manipulação e organização de dados.  \n   - `sqlite3`: Para armazenamento em banco de dados (opcional).  \n   - `tinydb`: Para armazenamento em banco de dados NoSQL.\n   - `sqlalchemy`: SQLAlchemy é uma biblioteca de mapeamento objeto-relacional para Python.\n   - `psycopg2-binary`: Psycopg é uma biblioteca de acesso a dados PostgreSQL para Python.\n   - `streamlit`: Para criar dashboards interativos.\n   - `time`: Para medir o tempo de execução do programa.\n   - `datetime`: Para manipulação de datas e horas.\n- **Coinbase API**: Para obter o preço da Bitcoin em tempo real.  \n\n---\n\n## **Exemplo de Dados Coletados**  \n| Data/Hora           | Preço (USD) | Moeda   |  \n|----------------------|------------|---------|  \n| 2024-01-01 12:00:00 | 42,000.50  | Bitcoin |  \n| 2024-01-01 13:00:00 | 42,150.75  | Bitcoin |  \n\n---\n\n## **Resultados Esperados**  \nAo final deste projeto, você será capaz de:  \n1. Extrair dados em tempo real de APIs públicas.  \n2. Transformar e organizar os dados em formato estruturado.  \n3. Automatizar o pipeline ETL para coleta recorrente dos dados.  \n\n**Exemplo de Análises Futuras**:  \n- Monitorar o preço da Bitcoin ao longo do tempo.  \n- Identificar padrões de variação diária, semanal ou mensal.  \n- Criar alertas para valores mínimos/máximos.  \n\n---\n\n## **Próximos Passos**  \nEste projeto é apenas o começo. Nos próximos módulos, cobriremos:  \n1. **Transformação Avançada**: Limpeza e enriquecimento dos dados.  \n2. **Armazenamento Persistente**: Introdução a bancos de dados em nuvem.  \n3. **Visualização de Dados**: Construção de dashboards interativos.  \n\n---\n\n## **Como Executar o Projeto**  \n\n1. **Clone o Repositório**:  \n   ```bash\n   git clone https://github.com/seu-usuario/data-pipeline-bitcoin.git\n   cd data-pipeline-bitcoin\n   ```\n\n2. **Instale as Dependências**:  \n   ```bash\n   pip install requests pandas\n   ```\n\n3. **Execute o Script**:  \n   ```bash\n   python main.py\n   ```\n\n4. **Verifique os Dados**:  \n   - O arquivo `bitcoin_prices.csv` será gerado com os preços coletados.  \n\n---\n\n**Agora, mãos à obra! 🚀**  \n\n--- \n\nEssa versão usa a **API pública da Coinbase** e adapta o fluxo do projeto para a captura do preço da Bitcoin. Ela é simples, funcional e ideal para iniciantes em Engenharia de Dados!\n\n## Realmente precisamos de uma API?\n\nA grande diferença entre o **consumo de memória do Selenium** e o **consumo de memória do requests** é resultado da **complexidade** e **funcionamento interno** das duas abordagens. Vamos analisar ponto a ponto:\n\n---\n\n## **Diferença Entre Selenium e Requests**\n\n1. **Selenium**:\n   - **Selenium** abre um **navegador real**, como o Google Chrome.\n   - O ChromeDriver **inicializa uma instância completa do navegador**, que carrega:\n     - HTML completo,\n     - CSS, JavaScript dinâmico,\n     - Imagens e outros recursos visuais.\n   - O navegador consome memória como qualquer navegador que você usaria manualmente.  \n   - O **processo principal Python** apenas controla o ChromeDriver, mas a maior parte da memória é consumida pelo **processo filho** (navegador).\n\n2. **Requests**:\n   - A biblioteca **`requests`** faz apenas uma **requisição HTTP simples** ao servidor.\n   - Ele **não carrega imagens, CSS, JavaScript ou renderiza nada**. Apenas recebe o **HTML cru ou JSON** como texto e o processa.  \n   - Como resultado, o consumo de memória é extremamente baixo, pois não há dependências complexas ou renderização.\n\n---\n\n## **Resultados Explicados**\n\n### **Selenium**\n```plaintext\n🔍 Memória inicial: 33.39 MB\n📈 Memória após abrir o navegador: 587.02 MB\n📈 Memória após carregar a página: 967.70 MB\n💰 Preço atual do Bitcoin (InfoMoney): 655.084,00\n📈 Memória após captura do preço: 963.44 MB\n🔻 Memória final após fechar o navegador: 21.14 MB\n🚀 Pico de memória do processo Python: 0.56 MB\n```\n\n**Explicação**:\n- **33 MB**: Memória inicial do Python, apenas carregando o interpretador e bibliotecas.\n- **587 MB**: O navegador foi aberto, e ele sozinho consome cerca de **500 MB** para funcionar.\n- **967 MB**: A página foi carregada com todos os recursos (scripts, imagens, etc.).\n- **Pico do Python (0.56 MB)**: O Selenium apenas **controla o navegador**, mas não aloca muito dentro do Python. O **navegador Chrome** (processo filho) consome a maior parte dos recursos.\n\n---\n\n### **Requests**\n```plaintext\nPico de memória durante a execução: 0.17 MB\n```\n\n**Explicação**:\n- A biblioteca `requests` apenas faz uma **requisição leve** e recebe uma resposta.  \n- Como não há renderização ou recursos pesados sendo carregados, o consumo de memória é **mínimo**.  \n- O pico de memória é extremamente baixo porque o Python armazena apenas o JSON (ou HTML) da resposta, que ocupa poucos KBs.\n\n---\n\n## **Por Que Essa Diferença Acontece?**\n\n| Aspecto                   | Selenium                               | Requests                   |\n|---------------------------|----------------------------------------|----------------------------|\n| **Execução**              | Abre um navegador completo (Chrome).   | Apenas faz uma requisição. |\n| **Carregamento**          | Renderiza HTML, CSS, JavaScript, etc.  | Processa apenas o texto.   |\n| **Processo Controlado**   | Processos filhos consomem memória.     | Apenas processo Python.    |\n| **Complexidade**          | Mais pesado devido ao ChromeDriver.    | Muito leve e direto.       |\n| **Pico de Memória Python**| Baixo: Python controla o ChromeDriver. | Leve: Apenas resposta HTTP.|\n\n---\n\n## **Conclusão**\n\n1. **Selenium**:\n   - É **muito mais pesado** porque ele abre e controla um navegador completo.\n   - O ChromeDriver e o navegador Chrome (processos filhos) consomem quase **1 GB** de RAM.\n\n2. **Requests**:\n   - É **muito mais leve** porque apenas faz uma requisição HTTP.\n   - Não há renderização ou carregamento de recursos extras, então o consumo é quase insignificante.\n\n---\n\n### **Quando Usar Cada Um?**\n\n- **Use Requests**:\n   - Quando o site oferece uma **API** ou os dados estão disponíveis diretamente no HTML sem necessidade de renderização dinâmica.\n\n- **Use Selenium**:\n   - Quando o site carrega conteúdo com **JavaScript** ou é necessário interagir com o navegador (cliques, scroll, etc.).\n\n---\n\nSe precisar otimizar ou escolher a melhor abordagem para um caso específico, é só avisar! 🚀\n\nQuando você entra em um **site** ou consome uma **API**, a comunicação entre o **cliente** (navegador ou aplicativo) e o **servidor** ocorre por meio de requisições e respostas. A **diferença principal** está no **conteúdo** enviado e recebido.\n\n---\n\n## **1. Diferença Entre Site e API**\n\n| **Aspecto**           | **Site**                                | **API**                               |\n|------------------------|----------------------------------------|--------------------------------------|\n| **Requisição**         | Feita pelo navegador (HTTP GET/POST).  | Feita pelo cliente (aplicação/script) via HTTP. |\n| **Resposta do Servidor**| HTML, CSS, JavaScript e recursos visuais (imagens, vídeos). | Dados estruturados (geralmente JSON ou XML). |\n| **Renderização**       | Navegador renderiza a página (front-end visual). | Cliente processa os dados e decide o uso. |\n| **Uso**                | Visualização para um usuário humano.   | Integração entre sistemas ou aplicações. |\n\n---\n\n## **2. Exemplos Práticos**\n\n1. **Site**:  \n   - O cliente (navegador) envia uma **requisição HTTP GET** para acessar a URL de um site.\n   - O servidor responde com um **HTML** que contém links para **CSS, JavaScript e imagens**.  \n   - O navegador **renderiza** todos esses arquivos para exibir a página.\n\n2. **API**:  \n   - O cliente (aplicação) envia uma **requisição HTTP GET/POST** para a URL da API.\n   - O servidor responde apenas com **dados estruturados** (exemplo: JSON ou XML).  \n   - Não há renderização visual; a resposta é processada diretamente pelo código.\n\n---\n\n## **3. Fluxo no Mermaid**\n\nAqui está o fluxo dos dois casos no formato **Mermaid**.\n\n### **Fluxo de um Site**\n```mermaid\nsequenceDiagram\n    participant Cliente as Navegador (Cliente)\n    participant Servidor as Servidor Web\n\n    Cliente-\u003e\u003eServidor: HTTP GET (Requisição para URL do site)\n    Servidor--\u003e\u003eCliente: HTML, CSS, JS, Imagens (Resposta)\n\n    Cliente-\u003e\u003eCliente: Renderiza HTML e carrega recursos\n```\n\n---\n\n### **Fluxo de uma API**\n```mermaid\nsequenceDiagram\n    participant Cliente as Aplicação (Cliente)\n    participant Servidor as Servidor de API\n\n    Cliente-\u003e\u003eServidor: HTTP GET/POST (Requisição para endpoint)\n    Servidor--\u003e\u003eCliente: JSON ou XML (Resposta)\n\n    Cliente-\u003e\u003eCliente: Processa os dados retornados\n```\n\n---\n\n## **Diferenças Claras nos Fluxos**\n\n1. **Site**:  \n   - O servidor envia um **HTML** que o navegador processa e renderiza.\n   - O HTML referencia **CSS**, **JavaScript**, e **imagens**, que são carregados separadamente.\n\n2. **API**:  \n   - O servidor retorna apenas **dados estruturados** em **JSON/XML**.\n   - A aplicação cliente consome e processa esses dados diretamente, sem renderização visual.\n\n---\n\nSe quiser, posso ajustar o fluxo para adicionar mais detalhes ou exemplos práticos. 🚀\n\n## **Banco de dados**\n\nVamos usar o Postgres, que é um banco de dados open source, gratuito e muito popular.\n\nPara instalar o Postgres, você pode usar o Docker, que é uma ferramenta que facilita a execução de contêineres de software.\n\nOu você pode usar o servidor de banco de dados da Render ou Azure que é um serviço de cloud computing que facilita a execução de contêineres de software.\n\n### Criando um servidor de banco de dados na Render\n\nA Render é uma plataforma de cloud computing que facilita a execução de contêineres de software.\n\nPara criar um servidor de banco de dados na Render, você pode usar o link: [Render](https://render.com/docs/databases)\n\nClique em **New** e **Postgres**\n\nColoque o nome do seu banco de dados, o usuário e a senha.\n\n### Criando a pipeline em Python\n\n---\n\n#### 1. `database.py`\n\nEsse arquivo é responsável por criar a tabela no banco de dados.\n\nO ORM (Object-Relational Mapping) é uma técnica que permite mapear objetos de um programa para tabelas de um banco de dados.\n\nDessa forma, você não precisa mais usar SQL puro para criar e manipular a tabela.\n\n```python\nclass BitcoinPreco(Base):\n    \"\"\"Define a tabela no banco de dados.\"\"\"\n    __tablename__ = \"bitcoin_precos\"\n\n    id = Column(Integer, primary_key=True, autoincrement=True)\n    valor = Column(Float, nullable=False)\n    criptomoeda = Column(String(50), nullable=False)  # até 50 caracteres\n    moeda = Column(String(10), nullable=False)        # até 10 caracteres\n    timestamp = Column(DateTime, default=datetime.now)\n```\n\nA classe `BitcoinPreco` define as colunas para uma tabela chamada `bitcoin_precos` no PostgreSQL. Aqui vai o **SQL bruto** que você pode usar para criar a tabela manualmente no PostgreSQL:\n\n```sql\nCREATE TABLE IF NOT EXISTS bitcoin_precos (\n    id SERIAL PRIMARY KEY,\n    valor DOUBLE PRECISION NOT NULL,\n    criptomoeda VARCHAR(50) NOT NULL,\n    moeda VARCHAR(10) NOT NULL,\n    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n);\n```\n\nEssa instrução **corresponde** à estrutura modelada em `BitcoinPreco` pelo SQLAlchemy. Se você quiser adequar o tamanho de cada `VARCHAR` ou usar outro tipo como `TEXT`, fique à vontade para ajustar conforme suas necessidades.\n\n---\n\n## 2. Arquivo principal (por exemplo, `pipeline_bitcoin_05.py`)\n\n```python\nimport os\nimport time\nimport requests\nfrom datetime import datetime\nfrom dotenv import load_dotenv\nfrom sqlalchemy import create_engine\nfrom sqlalchemy.orm import sessionmaker\n\n# Importar Base e BitcoinPreco do database.py\nfrom database import Base, BitcoinPreco\n\n# Carrega variáveis de ambiente do arquivo .env\nload_dotenv()\n\n# Lê as variáveis separadas do arquivo .env (sem SSL)\nPOSTGRES_USER = os.getenv(\"POSTGRES_USER\")\nPOSTGRES_PASSWORD = os.getenv(\"POSTGRES_PASSWORD\")\nPOSTGRES_HOST = os.getenv(\"POSTGRES_HOST\")\nPOSTGRES_PORT = os.getenv(\"POSTGRES_PORT\")\nPOSTGRES_DB = os.getenv(\"POSTGRES_DB\")\n\n# Monta a URL de conexão ao banco PostgreSQL (sem ?sslmode=...)\nDATABASE_URL = (\n    f\"postgresql://{POSTGRES_USER}:{POSTGRES_PASSWORD}\"\n    f\"@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}\"\n)\n\n# Cria o engine e a sessão\nengine = create_engine(DATABASE_URL)\nSession = sessionmaker(bind=engine)\n\ndef criar_tabela():\n    \"\"\"Cria a tabela no banco de dados, se não existir.\"\"\"\n    Base.metadata.create_all(engine)\n    print(\"Tabela criada/verificada com sucesso!\")\n\ndef extrair_dados_bitcoin():\n    \"\"\"Extrai o JSON completo da API da Coinbase.\"\"\"\n    url = 'https://api.coinbase.com/v2/prices/spot'\n    resposta = requests.get(url)\n    if resposta.status_code == 200:\n        return resposta.json()\n    else:\n        print(f\"Erro na API: {resposta.status_code}\")\n        return None\n\ndef tratar_dados_bitcoin(dados_json):\n    \"\"\"Transforma os dados brutos da API e adiciona timestamp.\"\"\"\n    valor = float(dados_json['data']['amount'])\n    criptomoeda = dados_json['data']['base']\n    moeda = dados_json['data']['currency']\n    timestamp = datetime.now()\n    \n    dados_tratados = {\n        \"valor\": valor,\n        \"criptomoeda\": criptomoeda,\n        \"moeda\": moeda,\n        \"timestamp\": timestamp\n    }\n    return dados_tratados\n\ndef salvar_dados_postgres(dados):\n    \"\"\"Salva os dados no banco PostgreSQL.\"\"\"\n    session = Session()\n    novo_registro = BitcoinPreco(**dados)\n    session.add(novo_registro)\n    session.commit()\n    session.close()\n    print(f\"[{dados['timestamp']}] Dados salvos no PostgreSQL!\")\n\nif __name__ == \"__main__\":\n    criar_tabela()\n    print(\"Iniciando ETL com atualização a cada 15 segundos... (CTRL+C para interromper)\")\n\n    while True:\n        try:\n            dados_json = extrair_dados_bitcoin()\n            if dados_json:\n                dados_tratados = tratar_dados_bitcoin(dados_json)\n                print(\"Dados Tratados:\", dados_tratados)\n                salvar_dados_postgres(dados_tratados)\n            time.sleep(15)\n        except KeyboardInterrupt:\n            print(\"\\nProcesso interrompido pelo usuário. Finalizando...\")\n            break\n        except Exception as e:\n            print(f\"Erro durante a execução: {e}\")\n            time.sleep(15)\n```\n\n---\n\n## 3. `.env` (Exemplo)\n\nNeste caso, seu arquivo `.env` também não conterá SSL:\n\n```bash\nPOSTGRES_USER=jornadadedados\nPOSTGRES_PASSWORD=mudar123\nPOSTGRES_HOST=bancodedadospostgres.postgres.database.azure.com\nPOSTGRES_PORT=5432\nPOSTGRES_DB=postgres\n```\n---\n\n### Como funciona agora\n\n1. **`database.py`**: contém apenas a definição de `Base` e do modelo `BitcoinPreco`.\n2. **`exemplo_05.py`** (ou outro nome principal): faz o ETL, cria a tabela usando `Base`, e salva os dados usando a instância da `Session`.  \n\nCom isso, você removeu completamente a parte de SSL.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandrecpedro%2Fcoinbaseapi_extract_etl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexandrecpedro%2Fcoinbaseapi_extract_etl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandrecpedro%2Fcoinbaseapi_extract_etl/lists"}