🚀 DAY 5 OF LAUNCH WEEK: Introducing Socket Firewall Enterprise.Learn more
Socket
Book a DemoInstallSign in
Socket

cei-crawler

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cei-crawler

Crawler para pegar dados do Canal Eletronico do Investidor

latest
Source
npmnpm
Version
3.0.1
Version published
Maintainers
1
Created
Source

cei-crawler 💸

Travis badge Coveralls badge License: MIT

Crawler para ler dados do Canal Eletrônico do Investidor

Importante (Versão sem captcha)

Para versão antiga do CEI que não possui captcha obrigatório (por enquanto), utilize o cei-crawler v2

Descrição

Essa versão do crawler varre a Nova Area Logada do CEI. Essa área logada possui um captcha para que seja feito o login e por isso existem algumas estratégias de implementação para fazer o bypass do mesmo. Além disso, o CEI agora possui uma API. Tudo que o crawler faz basicamente é encapsular as chamadas dessas API's. Portanto, o formato dos dados vem direto do CEI, não há transformação feita por esse crawler. Sendo assim, caso haja algo estranho ou errado nos dados retornados, provavelmente é o próprio CEI que está retornando.

O cei-crawler utiliza as seguintes dependências:

  • puppeteer-core para navegar com o browser e resolver o captcha.
  • axios para fazer as requisições http.

Sponsor

Caso o cei-crawler tenha te ajudado e você queira fazer alguma doação pra me ajudar a mantê-lo, utilize o QR code abaixo :) Mande também seu nome e usuário do GitHub (caso tenha) que eu coloco aqui no README. Obrigado!

PIX: joao.menighin@gmail.com

Advertisement

Criei o cei-crawler para um projeto de acompanhamento de investimentos. Caso esteja procurando algo nesse sentido, confira o Stoincs!

Instalação

Basta instalar utilizando o NPM:

npm install --save cei-crawler

Utilização

Crie uma instância do CeiCrawler passando os parametros necessários e invoque o método desejado:

let ceiCrawler = new CeiCrawler('username', 'password', {/* options */});
ceiCrawler.login(); // Login é opcional, pois antes de cada método o cei-crawler irá verificar se já esta logado.
                    // A vantagem em realizar o login em um passo diferente é para o tratamento de erros

Login & Captcha

A nova área logada do CEI possui validação por captcha. Não há forma simples de resolver e por isso algumas estratégias de resolução são implementadas. Essas estratégias são setadas na instanciação do crawler, com o objeto de options. As disponíveis são:

raw-token

Nessa estratégia de login, não é necessário informar usuário e senha porém deve-se informar o token e o cache-guid do usuário logado. Essa estratégia é útil caso você possua algum serviço terceiro que faça o login no CEI e pegue o token pra você.

Exemplo:

const ceiCrawler = new CeiCrawler(_, _, { 
    loginOptions: {
        strategy: 'raw-token'
    },
    auth: {
        "cache-guid": "cache-guid do usuário logado",
        token: "JWT do usuário logado"
    }
});

const values = await ceiCrawler.getConsolidatedValues();

user-resolve

Nessa estratégia de login, o usuário será promptado para fazer o login ele mesmo em uma janela de browser que será aberta. O crawler tenta preencher usuário e senha para você de forma que o input manual é somente para resolução do Captcha. Uma vez feito o login, o crawler trata de pegar as credencias e seguir adiante chamando os métodos. Nas opções do login deve-se também ser informado um caminho do browser para que o puppeteer o controle.

Exemplo:

const ceiCrawler = new CeiCrawler('user', 'password', { 
    loginOptions: {
        strategy: 'user-resolve',
        browserPath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
    }
});

const values = await ceiCrawler.getConsolidatedValues();

Métodos disponíveis

getConsolidatedValues()

Retorna os investimentos consolidados num valor total e divididos em subcategorias

let consolidated = await ceiCrawler.getConsolidatedValues();

Resultado:

{
  "total": 10000,
  "subTotais": [
    {
      "categoriaProduto": "Renda Variável",
      "totalPosicao": 5000,
      "percentual": 0.5
    },
    {
      "categoriaProduto": "Tesouro Direto",
      "totalPosicao": 5000,
      "percentual": 0.5
    }
  ]
}

getPosition(date, page)

Retorna as posições da tela "Posição" em todas as categorias de investimentos.

ParâmetroTipoDefaultDescrição
dateDtenullData da posição. Caso seja passado null ou nenhum valor, será usada a ultima data de processamento do CEI.
pageNumber1Paginação dos dados. Por default retorna a primeira página.
let position = await ceiCrawler.getPosition();

Resultado:

{
  "paginaAtual": 1,
  "totalPaginas": 1,
  "itens": [
    {
      "categoriaProduto": "RendaVariavel",
      "tipoProduto": "Acao",
      "descricaoTipoProduto": "Ações",
      "posicoes": [
        {
          "id": "gfw2455-8a79-4127-990b-587sa37",
          "temBloqueio": false,
          "instituicao": "INTER DISTRIBUIDORA DE TITULOS E VALORES MOBILIARIOS LTDA",
          "quantidade": 100,
          "valorAtualizado": 2377.00,
          "precoFechamento": 23.77,
          "produto": "BIDI4 - BANCO INTER S.A.",
          "tipo": "PN",
          "marcacoes": [],
          "codigoNegociacao": "BIDI4",
          "documentoInstituicao": "358743882",
          "existeLogotipo": false,
          "disponivel": 100,
          "documento": "48377283492",
          "razaoSocial": "BANCO INTER S.A.",
          "codigoIsin": "BRBRHEU2",
          "distribuicao": "114",
          "escriturador": "BANCO BRADESCO S/A",
          "valorBruto": 0
        }
      ],
      "totalPosicao": 2377.00,
      "totalItemsPagina": 1
    },
    {
      "categoriaProduto": "TesouroDireto",
      "tipoProduto": "TesouroDireto",
      "descricaoTipoProduto": "Tesouro Direto",
      "posicoes": [
        {
          "id": "hfd4564-e70a-4596-93fd-987654dvbhw",
          "temBloqueio": false,
          "instituicao": "XP INVESTIMENTOS CCTVM S/A",
          "quantidade": 1.01,
          "valorAtualizado": 2200,
          "vencimento": "2024-08-15T00:00:00",
          "valorAplicado": 2000,
          "produto": "Tesouro IPCA+ 2024",
          "marcacoes": [],
          "documentoInstituicao": "8573938583",
          "existeLogotipo": false,
          "indexador": "IPCA",
          "disponivel": 1.01,
          "documento": "7658493485",
          "codigoIsin": "VRSIYASU@",
          "valorBruto": 2038,
          "nomeTituloPublico": "Tesouro IPCA+ 2024",
          "valorLiquido": 29882,
          "percRentabilidadeContratada": 4.71
        }
      ],
      "totalPosicao": 22000,
      "totalItemsPagina": 5
    }
  ],
  "detalheStatusCode": 0,
  "excecoes": []
}

getPositionDetail(id, category, type)

Retorna o detalhe de uma posição da lista anterior.

ParâmetroTipoDefaultDescrição
idStringundefinedUUID da posição. Foi observado que o UUID de uma mesma posição pode mudar ao longo do tempo e essa requisição falhar após pegar a lista com o getPosition()
categoryStringundefinedCategoria da posição informada no método getPosition().
typeStringundefinedTipo da posição informada no método getPosition().
let positionDetail = await ceiCrawler.getPositionDetail('gfw2455-8a79-4127-990b-587sa37', 'RendaVariavel', 'Acao');

Resultado:

{
  "codigoIsin": "BRBIDIACNPR0",
  "distribuicao": "114",
  "empresa": "BANCO INTER S.A.",
  "escriturador": "BANCO BRADESCO S/A",
  "codigoNegociacao": "BIDI4",
  "disponivel": 100,
  "indisponivel": 0,
  "quantidade": 100,
  "marcacoes": [],
  "possuiMarcacoes": false,
  "existeLogotipo": false,
  "documentoInstituicao": "358743882"
}

getAccountStatement(startDate, endDate, page)

Retorna as movimentações da aba "Movimentação" no CEI.

ParâmetroTipoDefaultDescrição
startDateDatenullData de inicio para trazer as movimentações. Caso null, será utilizada a ultima data de processamento do CEI menos 1 mês.
endDateDatenullData fim para trazer as movimentações. Caso null, será utilizada a ultima data de processamento do CEI.
pageNumber1Paginação dos dados. Por default retorna a primeira página.
let accountStatement = await ceiCrawler.getAccountStatement();

Resultado:

{
  "paginaAtual": 1,
  "totalPaginas": 2,
  "itens": [
    {
      "data": "2021-08-02T00:00:00",
      "movimentacoes": [
        {
          "tipoOperacao": "Credito",
          "tipoMovimentacao": "Juros Sobre Capital Próprio",
          "nomeProduto": "BIDI4 - BANCO INTER S.A.",
          "instituicao": "INTER DISTRIBUIDORA DE TITULOS E VALORES MOBILIARIOS LTDA",
          "quantidade": 100,
          "valorOperacao": 1.49,
          "precoUnitario": 0.01
        }
      ],
      "totalItemsPagina": 1
    },
    {
      "data": "2021-07-30T00:00:00",
      "movimentacoes": [
        {
          "tipoOperacao": "Debito",
          "tipoMovimentacao": "Transferência",
          "nomeProduto": "ALZR11 - ALIANZA TRUST RENDA IMOBILIARIA FDO INV IMOB",
          "instituicao": "RICO INVESTIMENTOS - GRUPO XP",
          "quantidade": 5
        },
        {
          "tipoOperacao": "Credito",
          "tipoMovimentacao": "Transferência",
          "nomeProduto": "ALZR11 - ALIANZA TRUST RENDA IMOBILIARIA FDO INV IMOB",
          "instituicao": "XP INVESTIMENTOS CCTVM S/A",
          "quantidade": 5
        }
      ],
      "totalItemsPagina": 2
    }
  ],
  "detalheStatusCode": 0,
  "excecoes": []
}

getIpos(date, page)

Retorna os IPOs da tela "Ofertas Públicas" no CEI.

ParâmetroTipoDefaultDescrição
dateDatenullData de consulta. Caso seja passado null ou nenhum valor, será usada a ultima data de processamento do CEI.
pageNumber1Paginação dos dados. Por default retorna a primeira página.
let ipos = await ceiCrawler.getIPOs();

Resultado:

{
  "paginaAtual": 1,
  "totalPaginas": 1,
  "itens": [
    {
      "data": "2021-07-27T00:00:00",
      "ofertasPublicas": [
        {
          "id": "c80c8b8f-62d2-4b48-b242-b0f310cfa95a",
          "dataLiquidacao": "2021-07-27T00:00:00",
          "nomeEmpresa": "INVESTO ETF MSCI US TECHNOLOGY FDO INV IND INV EXT",
          "tipoOferta": "OUTRO",
          "oferta": "ETF INVESTO",
          "nomeInstituicao": "INTER DISTRIBUIDORA DE TITULOS E VALORES MOBILIARIOS LTDA",
          "quantidade": 10,
          "preco": 10,
          "valor": 100
        }
      ],
      "totalItemsPagina": 1
    }
  ],
  "detalheStatusCode": 0,
  "excecoes": []
}

getIPODetail(id)

Retorna o detalhe de uma posição da lista anterior.

ParâmetroTipoDefaultDescrição
idStringundefinedUUID do IPO. Foi observado que o UUID de um mesmo IPO pode mudar ao longo do tempo e essa requisição falhar após pegar a lista com o getIPOs()
let ipoDetail = await ceiCrawler.getIPODetail('c80c8b8f-62d2-4b48-b242-b0f310cfa95a');

Resultado:

{
  "nomeProduto": "OUTRO INVESTO ETF MSCI US TECHNOLOGY FDO INV IND INV EXT",
  "nomeInstituicao": "INTER DISTRIBUIDORA DE TITULOS E VALORES MOBILIARIOS LTDA",
  "ativo": {
    "nomeEmpresa": "INVESTO ETF MSCI US TECHNOLOGY FDO INV IND INV EXT",
    "ticker": "USTK11L",
    "oferta": "ETF INVESTO",
    "codigoIsin": "BRUSTKCTF007"
  },
  "valores": {
    "preco": 10,
    "precoMaximo": 0,
    "valor": 100
  },
  "reserva": {
    "modalidade": "Compra/Integralização de cotas do ETF INVESTO",
    "quantidade": 10,
    "valor": 0
  },
  "quantidadeAlocada": 10,
  "dataLiquidacao": "2021-07-27T00:00:00"
}

getStockTransactions(startDate, endDate, page)

Retorna os dados da aba "Negociação" no CEI.

ParâmetroTipoDefaultDescrição
startDateDatenullData de inicio para trazer as negociações. Caso null, será utilizada a ultima data de processamento do CEI menos 1 mês.
endDateDatenullData fim para trazer as negociações. Caso null, será utilizada a ultima data de processamento do CEI.
pageNumber1Paginação dos dados. Por default retorna a primeira página.
let stockTransactions = await ceiCrawler.getStockTransactions();

Resultado:

{
  "paginaAtual": 1,
  "totalPaginas": 1,
  "itens": [
    {
      "data": "2021-07-20T00:00:00",
      "totalCompra": 1000,
      "totalVenda": 0,
      "negociacaoAtivos": [
        {
          "tipoMovimentacao": "Compra",
          "mercado": "Mercado à Vista",
          "nomeInstituicao": "RICO INVESTIMENTOS - GRUPO XP",
          "codigoNegociacao": "PNVL3",
          "quantidade": 100,
          "preco": 10.00,
          "valor": 1000.00
        }
      ],
      "totalItemsPagina": 1
    }
  ],
  "detalheStatusCode": 0,
  "excecoes": []
}

getProvisionedEvents(date, page)

Retorna os eventos da tela "Eventos Provisionados" no CEI.

ParâmetroTipoDefaultDescrição
dateDatenullData de consulta. Caso seja passado null ou nenhum valor, será usada a ultima data de processamento do CEI.
pageNumber1Paginação dos dados. Por default retorna a primeira página.
let events = await ceiCrawler.getProvisionedEvents();

Resultado:

{
  "totalValorLiquido": 8.62,
  "paginaAtual": 1,
  "totalPaginas": 1,
  "itens": [
    {
      "id": "9cc87804-f9ae-143a-acfb-c953f38c72dd",
      "produto": "WEGE3        - WEG S/A",
      "tipo": "ON",
      "tipoEvento": "JUROS SOBRE CAPITAL PRÓPRIO",
      "previsaoPagamento": "2021-08-11T00:00:00",
      "instituicao": "INTER DISTRIBUIDORA DE TITULOS E VALORES MOBILIARIOS LTDA",
      "quantidade": 300,
      "precoUnitario": 0.03,
      "valorLiquido": 8.62,
      "totalItemsPagina": 1
    }
  ],
  "detalheStatusCode": 0,
  "excecoes": []
}

getProvisionedEventDetail(id)

Retorna o detalhe de um evento provisionado da lista anterior.

ParâmetroTipoDefaultDescrição
idStringundefinedUUID do evento. Foi observado que o UUID de um mesmo evento pode mudar ao longo do tempo e essa requisição falhar após pegar a lista com o getProvisionedEvents()
let eventDetail = await ceiCrawler.getProvisionedEventDetail('9cc87804-f9ae-143a-acfb-c953f38c72dd');

Resultado:

{
  "codigoNegociacao": "WEGE3",
  "codigoIsin": "BRWEGEACNOR0",
  "distribuicao": "202",
  "escriturador": "BANCO BRADESCO S/A",
  "empresa": "WEG S/A",
  "dataAprovacao": "2021-03-23T00:00:00",
  "dataAtualizacao": "2021-03-30T00:00:00",
  "dataEx": "2021-03-29T00:00:00",
  "impostoRenda": 15,
  "valorImpostoRenda": 1.52,
  "valorBruto": 10.14,
  "disponivel": 100,
  "indisponivel": 0,
  "produto": "WEGE3        - WEG S/A",
  "tipo": "ON",
  "tipoEvento": "JUROS SOBRE CAPITAL PRÓPRIO",
  "previsaoPagamento": "2021-08-11T00:00:00",
  "quantidade": 100,
  "precoUnitario": 0.03,
  "valorLiquido": 8.62
}

Opções

Na criação de um CeiCrawler é possivel especificar alguns valores para o parâmetro options que modificam a forma que o crawler funciona. As opções são:

PropriedadeTipoDefaultDescrição
debugBooleanfalseSe true, printa mensages de debug no log.
loginOptions.strategyStringuser-resolveEstratégia utilizada no login. Veja Login & Captcha para mais informações.
loginOptions.browserPathStringundefinedCaminho para o executavél do browser que será controlado para resolucao do Captcha. Veja Login & Captcha para mais informações.
auth.tokenStringundefinedToken JWT do usuário logado no CEI. Utilizado quando a estratégia de login é raw-token
auth.cache-guidStringundefinedUUID da sessão do usuário logado no CEI. Utilizado quando a estratégia de login é raw-token

Exemplo:

const ceiCrawlerOptions = {
    debug: true,
    loginOptions: {
      strategy: 'user-resolve',
      browserPath: 'path/to/browser.exe'
    }
};

let ceiCrawler = new CeiCrawler('username', 'password', ceiCrawlerOptions);

Error Handling

O CEI Crawler possui um exceção própria, CeiCrawlerError, que é lançada em alguns cenários. Essa exceção possui um atributo type para te direcionar no tratamento:

typeDescrição
UNAUTHORIZEDLançada quando uma request retorna 401. Isso pode significar que o token utiliza é inválido ou expirou.
BAD_REQUESTLançada quando uma requisição falha por má formação. Pode ser um parâmetro errado, uma data menor que o limite minimo, etc.
TOO_MANY_REQUESTSO CEI faz throttling de requisições. Se ao usar o crawler você fizer muitas requisições rapidamente esse erro pode ser retornado
INVALID_LOGIN_STRATEGYLançada quando informada uma estratégia de login inválida.

Exemplo de como fazer um bom tratamento de erros:

const CeiCrawler = require('cei-crawler');
const { CeiErrorTypes } = require('cei-crawler')

const ceiCrawler = new CeiCrawler('usuario', 'senha', { navigationTimeout: 20000 });

try {
  const positions = ceiCrawler.getPositions();
} catch (err) {
  if (err.name === 'CeiCrawlerError') {
    if (err.type === CeiErrorTypes.UNAUTHORIZED)
      // Handle unauthrozied
    else if (err.type === CeiErrorTypes.TOO_MANY_REQUESTS)
      // Handle too many requests
    // else ...
  } else {
    // Handle generic errors
  }
}

Licença

MIT

Keywords

cei

FAQs

Package last updated on 22 Nov 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts