├── __init__.py ├── bc ├── __init__.py └── bancocentral.py ├── sample ├── __init__.py └── sample.py ├── tests ├── __init__.py └── test_bancocentral.py ├── .flake8 ├── setup.cfg ├── .coveragerc ├── requirements.txt ├── .deepsource.toml ├── .github └── workflows │ └── main.yml ├── LICENSE ├── setup.py ├── .gitignore └── README.md /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E501 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = **__init__.py, **/sample*.py, **/test*.py 3 | 4 | [report] 5 | show_missing = false 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2021.10.8 2 | chardet==4.0.0 3 | coverage==6.1.2 4 | idna==3.3 5 | requests==2.26.0 6 | urllib3==1.26.7 7 | -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "python" 5 | enabled = true 6 | 7 | [analyzers.meta] 8 | runtime_version = "3.x.x" 9 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: bancocentralbrasil 2 | on: [push, pull_request] 3 | jobs: 4 | run: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | 9 | - name: Set up Python 3.7 10 | uses: actions/setup-python@v2 11 | with: 12 | python-version: 3.7 13 | 14 | - name: Install dependencies 15 | run: | 16 | python -m pip install --upgrade pip 17 | pip install -r requirements.txt 18 | pip install codecov 19 | 20 | - name: Run Tests 21 | run: | 22 | python -m unittest 23 | 24 | - name: Run coverage 25 | run: | 26 | python -m coverage run --source=bc tests/test_bancocentral.py 27 | codecov -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Leonardo Gregianin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sample/sample.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from bc.bancocentral import Inflacao, Poupanca, Cambio, Selic 5 | 6 | inflacao = Inflacao() 7 | print(u'Inflação Meta: %s' % inflacao.get_meta_tax()) 8 | print(u'Inflação acumulada 12 últimos meses: %s' % inflacao.get_acumulada_tax()) 9 | 10 | poupanca = Poupanca() 11 | print(u'Poupança: %s' % poupanca.get_poupanca_tax()) 12 | 13 | cambio = Cambio() 14 | print(u'Dólar compra PTAX: %s' % cambio.get_dolar_compra_ptax()) 15 | print(u'Dólar venda PTAX: %s' % cambio.get_dolar_venda_ptax()) 16 | print(u'Dólar PTAX em %s' % cambio.get_data_dolar_ptax()) 17 | print(u'Dólar compra: %s' % cambio.get_dolar_compra()) 18 | print(u'Dólar venda: %s' % cambio.get_dolar_venda()) 19 | print(u'Dólar em %s' % cambio.get_data_dolar()) 20 | print(u'Euro compra PTAX: %s' % cambio.get_euro_compra_ptax()) 21 | print(u'Euro venda PTAX: %s' % cambio.get_euro_venda_ptax()) 22 | print(u'Euro PTAX em %s' % cambio.get_data_euro_ptax()) 23 | print(u'Euro compra: %s' % cambio.get_euro_compra()) 24 | print(u'Euro venda: %s' % cambio.get_euro_venda()) 25 | print(u'Euro em %s' % cambio.get_data_euro()) 26 | 27 | selic = Selic() 28 | print(u'Selic meta: %s em %s' % (selic.get_selic_meta(), selic.get_data_selic_meta())) 29 | print(u'Selic real: %s em %s' % (selic.get_selic_real(), selic.get_data_selic_real())) 30 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | requirements = [ 5 | "requests>2,<3", 6 | ] 7 | test_requirements = ["coverage"] 8 | 9 | setup( 10 | name='bancocentralbrasil', 11 | version='1.2.0', 12 | url='https://github.com/leogregianin/bancocentralbrasil', 13 | license='LICENSE', 14 | author='Leonardo Gregianin', 15 | author_email='leogregianin@gmail.com', 16 | keywords='dolar money bancocentralbrasil tax brasil', 17 | description='Selic Rate, Inflation and Dollar Exchange from Brazil', 18 | packages=find_packages(), 19 | platforms='any', 20 | classifiers=[ 21 | 'Programming Language :: Python', 22 | 'Programming Language :: Python :: 2', 23 | 'Programming Language :: Python :: 2.7', 24 | 'Programming Language :: Python :: 3', 25 | 'Programming Language :: Python :: 3.5', 26 | 'Development Status :: 5 - Production/Stable', 27 | 'Natural Language :: English', 28 | 'Environment :: Console', 29 | 'Intended Audience :: Developers', 30 | 'License :: OSI Approved :: MIT License', 31 | 'Operating System :: OS Independent', 32 | 'Topic :: Software Development :: Libraries :: Python Modules' 33 | ], 34 | install_requires=[requirements], 35 | test_suite="tests", 36 | tests_require=test_requirements, 37 | ) 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | .vscode 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *,cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # IPython Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # dotenv 80 | .env 81 | 82 | # virtualenv 83 | venv/ 84 | ENV/ 85 | 86 | # Spyder project settings 87 | .spyderproject 88 | 89 | # Rope project settings 90 | .ropeproject 91 | /.pypirc 92 | /.idea/.gitignore 93 | /.idea/bancocentralbrasil.iml 94 | /.idea/inspectionProfiles/profiles_settings.xml 95 | /.idea/misc.xml 96 | /.idea/modules.xml 97 | /.idea/vcs.xml 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Banco Central do Brasil 2 | 3 | [![bancocentralbrasil](https://github.com/open-bacen/bancocentralbrasil/actions/workflows/main.yml/badge.svg)](https://github.com/open-bacen/bancocentralbrasil/actions/workflows/main.yml) 4 | [![codecov](https://codecov.io/gh/open-bacen/bancocentralbrasil/branch/main/graph/badge.svg)](https://codecov.io/gh/open-bacen/bancocentralbrasil) 5 | 6 | 7 | Sobre 8 | ------- 9 | 10 | * Informações sobre taxas oficiais diárias de **Inflação**, **Selic**, **Poupança**, **Dólar**, **Dólar PTAX**, **Euro** e **Euro PTAX** pelo site do Banco Central do Brasil (http://www.bcb.gov.br). 11 | 12 | Desenvolvimento 13 | ------- 14 | 15 | ```sh 16 | $ virtualenv .venv 17 | $ source .venv/bin/activate 18 | ``` 19 | 20 | Instalação das dependências 21 | ------- 22 | 23 | ```bash 24 | $ pip install -r requirements.txt 25 | ``` 26 | 27 | Instalação 28 | ------- 29 | 30 | ```bash 31 | $ ./setup.py install 32 | ``` 33 | 34 | Utilização 35 | ------- 36 | 37 | ```bash 38 | $ python ./sample.py 39 | nflação Meta: 3.75 40 | Inflação acumulada 12 últimos meses: 8.99 41 | Poupança: 0.3012 42 | Dólar compra PTAX: 5.4174 43 | Dólar venda PTAX: 5.418 44 | Dólar PTAX em 19/08/2021 16:07:17 45 | Dólar compra: 5.4174 46 | Dólar venda: 5.418 47 | Dólar em 19/08/2021 16:07:17 48 | Euro compra PTAX: 6.3335 49 | Euro venda PTAX: 6.3364 50 | Euro PTAX em 19/08/2021 16:07:17 51 | Euro compra: 6.3335 52 | Euro venda: 6.3364 53 | Euro em 19/08/2021 16:07:17 54 | Selic meta: 5.25 em 04/08/2021 55 | Selic real: 5.15 em 19/08/2021 56 | ``` 57 | 58 | ```bash 59 | >>> from bc.bancocentral import Inflacao 60 | >>> inflacao = Inflacao() 61 | >>> print('%s' % inflacao.get_acumulada_tax()) 62 | 4.53 63 | ``` 64 | 65 | ```bash 66 | >>> from bc.bancocentral import Selic 67 | >>> selic = bancocentral.Selic() 68 | >>> selic.get_selic_meta() 69 | 6.5 70 | ``` 71 | 72 | Testes e cobertura 73 | --------- 74 | 75 | ```bash 76 | $ python -m unittest 77 | .............................. 78 | ---------------------------------------------------------------------- 79 | Ran 30 tests in 47.580s 80 | 81 | OK 82 | ``` 83 | 84 | ```bash 85 | $ python -m coverage run --source=bc tests/test_bancocentral.py 86 | .............................. 87 | ---------------------------------------------------------------------- 88 | Ran 30 tests in 64.135s 89 | 90 | OK 91 | ``` 92 | 93 | ```bash 94 | $ coverage report 95 | $ coverage html 96 | ``` 97 | 98 | 99 | Licença 100 | ------- 101 | 102 | [Licença MIT](LICENSE) 103 | -------------------------------------------------------------------------------- /tests/test_bancocentral.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import unittest 5 | from unittest.mock import patch, MagicMock 6 | from bc.bancocentral import ( 7 | AcessarBancoCentral, 8 | DataCotacaoNotFound, 9 | AttributeNotFound, 10 | Inflacao, 11 | Poupanca, 12 | Cambio, 13 | Selic, 14 | ) 15 | 16 | 17 | def request_com_erro(): 18 | return MagicMock(status_code=503) 19 | 20 | 21 | def request_bem_sucedido(): 22 | return MagicMock(status_code=200) 23 | 24 | 25 | class TestCase(unittest.TestCase): 26 | 27 | def setUp(self): 28 | self.inflacao = Inflacao() 29 | self.poupanca = Poupanca() 30 | self.cambio = Cambio() 31 | self.selic = Selic() 32 | 33 | self.acesso = AcessarBancoCentral('http://my.url') 34 | 35 | # Retry 36 | @patch('bc.bancocentral.requests.get', return_value=request_com_erro()) 37 | def test_nao_retorna_request_com_erro(self, mock_request): 38 | self.assertIsNone(self.acesso.getURL()) 39 | 40 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 41 | def test_retorna_request_bem_sucedido(self, mock_request): 42 | response = self.acesso.getURL() 43 | self.assertIsNotNone(response) 44 | self.assertEqual(response.status_code, 200) 45 | 46 | @patch('bc.bancocentral.requests.get') 47 | def test_repete_request_enquanto_receber_erros(self, mock_request): 48 | requests = iter([request_com_erro(), request_bem_sucedido()]) 49 | mock_request.side_effect = lambda *args, **kwargs: next(requests) 50 | 51 | self.assertIsNotNone(self.acesso.getURL()) 52 | 53 | # Inflação 54 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 55 | def test_inflacao_meta(self, mock_request): 56 | self.assertIsNotNone(self.inflacao.get_meta_tax()) 57 | 58 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 59 | def test_inflacao_meta_maior_zero(self, mock_request): 60 | self.assertTrue(self.inflacao.get_meta_tax() > 0) 61 | 62 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 63 | def test_inflacao_acumulada(self, mock_request): 64 | self.assertIsNotNone(self.inflacao.get_acumulada_tax()) 65 | 66 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 67 | def test_inflacao_acumulada_maior_zero(self, mock_request): 68 | self.assertTrue(self.inflacao.get_acumulada_tax() > 0) 69 | 70 | # Poupança 71 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 72 | def test_poupanca(self, mock_request): 73 | self.assertIsNotNone(self.poupanca.get_poupanca_tax()) 74 | 75 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 76 | def test_poupanca_maior_zero(self, mock_request): 77 | self.assertTrue(self.poupanca.get_poupanca_tax() > 0) 78 | 79 | # Dólar 80 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 81 | def test_dolar_compra(self, mock_request): 82 | self.assertIsNotNone(self.cambio.get_dolar_compra()) 83 | 84 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 85 | def test_dolar_compra_ptax(self, mock_request): 86 | self.assertIsNotNone(self.cambio.get_dolar_compra_ptax()) 87 | 88 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 89 | def test_dolar_compra_maior_zero(self, mock_request): 90 | self.assertTrue(self.cambio.get_dolar_compra() > 0) 91 | 92 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 93 | def test_dolar_compra_ptax_maior_zero(self, mock_request): 94 | self.assertTrue(self.cambio.get_dolar_compra_ptax() > 0) 95 | 96 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 97 | def test_dolar_venda(self, mock_request): 98 | self.assertIsNotNone(self.cambio.get_dolar_venda()) 99 | 100 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 101 | def test_get_data_dolar(self, mock_request): 102 | self.assertIsNotNone(self.cambio.get_data_dolar()) 103 | 104 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 105 | def test_dolar_venda_ptax(self, mock_request): 106 | self.assertIsNotNone(self.cambio.get_dolar_venda_ptax()) 107 | 108 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 109 | def test_get_data_dolar_ptax(self, mock_request): 110 | self.assertIsNotNone(self.cambio.get_data_dolar_ptax()) 111 | 112 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 113 | def test_dolar_venda_maior_zero(self, mock_request): 114 | self.assertTrue(self.cambio.get_dolar_venda() > 0) 115 | 116 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 117 | def test_dolar_venda_ptax_maior_zero(self, mock_request): 118 | self.assertTrue(self.cambio.get_dolar_venda_ptax() > 0) 119 | 120 | # Euro 121 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 122 | def test_euro_compra(self, mock_request): 123 | self.assertIsNotNone(self.cambio.get_euro_compra()) 124 | 125 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 126 | def test_euro_compra_maior_zero(self, mock_request): 127 | self.assertTrue(self.cambio.get_euro_compra() > 0) 128 | 129 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 130 | def test_euro_venda(self, mock_request): 131 | self.assertIsNotNone(self.cambio.get_euro_venda()) 132 | 133 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 134 | def test_get_data_euro(self, mock_request): 135 | self.assertIsNotNone(self.cambio.get_data_euro()) 136 | 137 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 138 | def test_euro_venda_maior_zero(self, mock_request): 139 | self.assertTrue(self.cambio.get_euro_venda() > 0) 140 | 141 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 142 | def test_euro_compra_ptax(self, mock_request): 143 | self.assertIsNotNone(self.cambio.get_euro_compra_ptax()) 144 | 145 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 146 | def test_get_data_euro_ptax(self, mock_request): 147 | self.assertIsNotNone(self.cambio.get_data_euro_ptax()) 148 | 149 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 150 | def test_euro_compra_ptax_maior_zero(self, mock_request): 151 | self.assertTrue(self.cambio.get_euro_compra_ptax() > 0) 152 | 153 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 154 | def test_euro_venda_ptax(self, mock_request): 155 | self.assertIsNotNone(self.cambio.get_euro_venda_ptax()) 156 | 157 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 158 | def test_euro_venda_ptax_maior_zero(self, mock_request): 159 | self.assertTrue(self.cambio.get_euro_venda_ptax() > 0) 160 | 161 | # Taxa Selic 162 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 163 | def test_selic_meta(self, mock_request): 164 | self.assertIsNotNone(self.selic.get_selic_meta()) 165 | 166 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 167 | def test_selic_meta_maior_zero(self, mock_request): 168 | self.assertTrue(self.selic.get_selic_meta() > 0) 169 | 170 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 171 | def test_selic_real(self, mock_request): 172 | self.assertIsNotNone(self.selic.get_selic_real()) 173 | 174 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 175 | def test_selic_real_maior_zero(self, mock_request): 176 | self.assertTrue(self.selic.get_selic_real() > 0) 177 | 178 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 179 | def test_get_data_selic_meta(self, mock_request): 180 | self.assertIsNotNone(self.selic.get_data_selic_meta()) 181 | 182 | @patch('bc.bancocentral.requests.get', return_value=request_bem_sucedido()) 183 | def test_get_data_selic_real(self, mock_request): 184 | self.assertIsNotNone(self.selic.get_data_selic_real()) 185 | 186 | # clean Content 187 | def test_cleanContent(self): 188 | mock = "><>\r\n'" 189 | lista = ["<", "", ">", "", "<", ">", "\r\n"] 190 | mock = self.acesso.cleanContent(mock) 191 | self.assertFalse(([i in mock for i in lista].count(True)) == 0) 192 | 193 | def test_exceptions_datacotacao(self): 194 | with self.assertRaises(DataCotacaoNotFound) as exp: 195 | raise DataCotacaoNotFound 196 | error = exp.exception 197 | self.assertEqual(str(error), "Não foi possível capturar os dados do site") 198 | 199 | def test_exceptions_attribute(self): 200 | with self.assertRaises(AttributeNotFound) as exp: 201 | raise AttributeNotFound 202 | error = exp.exception 203 | self.assertEqual(str(error), "Atributo não encontrado") 204 | 205 | 206 | if __name__ == '__main__': 207 | unittest.main() 208 | -------------------------------------------------------------------------------- /bc/bancocentral.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import requests 5 | import re 6 | 7 | 8 | class DataCotacaoNotFound(Exception): 9 | def __str__(self): 10 | return "Não foi possível capturar os dados do site" 11 | 12 | 13 | class AttributeNotFound(Exception): 14 | def __str__(self): 15 | return "Atributo não encontrado" 16 | 17 | 18 | class AcessarBancoCentral: 19 | 20 | def __init__(self, url): 21 | self.url = url 22 | 23 | def getURL(self): 24 | headers = { 25 | 'Host': 'conteudo.bcb.gov.br', 26 | 'Connection': 'keep-alive', 27 | 'Cache-Control': 'max-age=0', 28 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', 29 | 'DNT': '1', 30 | 'Content-Type': 'application/atom+xml', 31 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 32 | 'Accept-Encoding': 'gzip, deflate, br', 33 | 'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,mt;q=0.6' 34 | } 35 | 36 | # Server very unstable. Test 10x http 200 response 37 | for _ in range(10): 38 | try: 39 | request = requests.get(self.url, headers=headers, timeout=50) 40 | if request.status_code != 200: 41 | continue 42 | return request 43 | except requests.ConnectionError: 44 | continue 45 | 46 | @staticmethod 47 | def cleanContent(content): 48 | fix = {'<': '<', '>': '>'} 49 | for key, value in fix.items(): 50 | content = content.replace(key, value) 51 | content = content.replace('\r\n', '') 52 | content = content.replace('/> Meta
(\d*[\.\,]?\d+)
', inflacao) 66 | if not tax: 67 | raise DataCotacaoNotFound 68 | return float(tax.group(1).replace(',', '.')) 69 | 70 | def get_acumulada_tax(self): 71 | inflacao = self.acesso.cleanContent(self.req.content.decode('utf-8')) 72 | tax = re.search(r'
Acumulada
(\d*[\.\,]?\d+)
', inflacao) 73 | if not tax: 74 | raise DataCotacaoNotFound 75 | return float(tax.group(1).replace(',', '.')) 76 | 77 | 78 | class Poupanca: 79 | 80 | def __init__(self): 81 | self.query_url = 'https://conteudo.bcb.gov.br/api/feed/pt-br/PAINEL_INDICADORES/poupanca' 82 | self.acesso = AcessarBancoCentral(self.query_url) 83 | self.req = self.acesso.getURL() 84 | 85 | def get_poupanca_tax(self): 86 | poupanca = self.acesso.cleanContent(self.req.content.decode('utf-8')) 87 | tax = re.search(r'
(\d*[\.\,]?\d+)
', poupanca) 88 | if not tax: 89 | raise DataCotacaoNotFound 90 | return float(tax.group(1).replace(',', '.')) 91 | 92 | 93 | class Cambio: 94 | 95 | def __init__(self): 96 | self.query_url = 'https://conteudo.bcb.gov.br/api/feed/pt-br/PAINEL_INDICADORES/cambio' 97 | self.acesso = AcessarBancoCentral(self.query_url) 98 | self.req = self.acesso.getURL() 99 | self.cambio = self.acesso.cleanContent(self.req.content.decode('utf-8')) 100 | 101 | def get_dolar_compra_ptax(self): 102 | data = re.search(r'INDICADOR_CAMBIO_DOLAR_PTAX(.*)', self.cambio) 103 | if not data: 104 | raise DataCotacaoNotFound 105 | compra = re.search(r'
Compra
(\d*[\.\,]?\d+)
', data.group(1)) 106 | if not compra: 107 | raise DataCotacaoNotFound 108 | return float(compra.group(1).replace(',', '.')) 109 | 110 | def get_dolar_venda_ptax(self): 111 | data = re.search(r'INDICADOR_CAMBIO_DOLAR_PTAX(.*)', self.cambio) 112 | if not data: 113 | raise DataCotacaoNotFound 114 | venda = re.search(r'
Venda
(\d*[\.\,]?\d+)
', data.group(1)) 115 | if not venda: 116 | raise DataCotacaoNotFound 117 | return float(venda.group(1).replace(',', '.')) 118 | 119 | def get_data_dolar_ptax(self): 120 | data = re.search(r'INDICADOR_CAMBIO_DOLAR_PTAX(.*)', self.cambio) 121 | if not data: 122 | raise DataCotacaoNotFound 123 | search = re.search(r'
[a-zA-Z\s]*([\d/]+\s[\d:]+)
', data.group(1)) 124 | if not search: 125 | raise AttributeNotFound 126 | return search.group(1) 127 | 128 | def get_dolar_compra(self): 129 | data = re.search(r'INDICADOR_CAMBIO_DOLAR(.*)', self.cambio) 130 | if not data: 131 | raise DataCotacaoNotFound 132 | compra = re.search(r'
Compra
(\d*[\.\,]?\d+)
', data.group(1)) 133 | if not compra: 134 | raise DataCotacaoNotFound 135 | return float(compra.group(1).replace(',', '.')) 136 | 137 | def get_dolar_venda(self): 138 | data = re.search(r'INDICADOR_CAMBIO_DOLAR(.*)', self.cambio) 139 | if not data: 140 | raise DataCotacaoNotFound 141 | venda = re.search(r'
Venda
(\d*[\.\,]?\d+)
', data.group(1)) 142 | if not venda: 143 | raise DataCotacaoNotFound 144 | return float(venda.group(1).replace(',', '.')) 145 | 146 | def get_data_dolar(self): 147 | data = re.search(r'INDICADOR_CAMBIO_DOLAR(.*)', self.cambio) 148 | if not data: 149 | raise DataCotacaoNotFound 150 | search = re.search(r'
[a-zA-Z\s]*([\d/]+\s[\d:]+)
', data.group(1)) 151 | if not search: 152 | raise AttributeNotFound 153 | return search.group(1) 154 | 155 | def get_euro_compra_ptax(self): 156 | data = re.search(r'INDICADOR_CAMBIO_EURO_PTAX(.*)', self.cambio) 157 | if not data: 158 | raise DataCotacaoNotFound 159 | compra = re.search(r'
Compra
(\d*[\.\,]?\d+)
', data.group(1)) 160 | if not compra: 161 | raise DataCotacaoNotFound 162 | return float(compra.group(1).replace(',', '.')) 163 | 164 | def get_euro_venda_ptax(self): 165 | data = re.search(r'INDICADOR_CAMBIO_EURO_PTAX(.*)', self.cambio) 166 | if not data: 167 | raise DataCotacaoNotFound 168 | venda = re.search(r'
Venda
(\d*[\.\,]?\d+)
', data.group(1)) 169 | if not venda: 170 | raise DataCotacaoNotFound 171 | return float(venda.group(1).replace(',', '.')) 172 | 173 | def get_data_euro_ptax(self): 174 | data = re.search(r'INDICADOR_CAMBIO_EURO_PTAX(.*)', self.cambio) 175 | if not data: 176 | raise DataCotacaoNotFound 177 | search = re.search(r'
[a-zA-Z\s]*([\d/]+\s[\d:]+)
', data.group(1)) 178 | if not search: 179 | raise AttributeNotFound 180 | return search.group(1) 181 | 182 | def get_euro_compra(self): 183 | data = re.search(r'INDICADOR_CAMBIO_EURO(.*)', self.cambio) 184 | if not data: 185 | raise DataCotacaoNotFound 186 | compra = re.search(r'
Compra
(\d*[\.\,]?\d+)
', data.group(1)) 187 | if not compra: 188 | raise DataCotacaoNotFound 189 | return float(compra.group(1).replace(',', '.')) 190 | 191 | def get_euro_venda(self): 192 | data = re.search(r'INDICADOR_CAMBIO_EURO(.*)', self.cambio) 193 | if not data: 194 | raise DataCotacaoNotFound 195 | venda = re.search(r'
Venda
(\d*[\.\,]?\d+)
', data.group(1)) 196 | if not venda: 197 | raise DataCotacaoNotFound 198 | return float(venda.group(1).replace(',', '.')) 199 | 200 | def get_data_euro(self): 201 | data = re.search(r'INDICADOR_CAMBIO_EURO(.*)', self.cambio) 202 | if not data: 203 | raise DataCotacaoNotFound 204 | search = re.search(r'
[a-zA-Z\s]*([\d/]+\s[\d:]+)
', data.group(1)) 205 | if not search: 206 | raise AttributeNotFound 207 | return search.group(1) 208 | 209 | 210 | class Selic: 211 | 212 | def __init__(self): 213 | self.query_url = 'https://conteudo.bcb.gov.br/api/feed/pt-br/PAINEL_INDICADORES/juros' 214 | self.acesso = AcessarBancoCentral(self.query_url) 215 | self.req = self.acesso.getURL() 216 | 217 | def get_selic_meta(self): 218 | selic = self.acesso.cleanContent(self.req.content.decode('utf-8')) 219 | selic_meta = re.search(r'
(\d*[\.\,]?\d+)
', selic) 220 | if not selic_meta: 221 | raise DataCotacaoNotFound 222 | return float(selic_meta.group(1).replace(',', '.')) 223 | 224 | def get_data_selic_meta(self): 225 | selic = self.acesso.cleanContent(self.req.content.decode('utf-8')) 226 | search = re.search(r'([\d/]+)
', selic) 227 | if not search: 228 | raise AttributeNotFound 229 | return search.group(1) 230 | 231 | def get_selic_real(self): 232 | selic = self.acesso.cleanContent(self.req.content.decode('utf-8')) 233 | selic_real = re.search(r'
(\d*[\.\,]?\d+)
', selic) 234 | if not selic_real: 235 | raise DataCotacaoNotFound 236 | return float(selic_real.group(1).replace(',', '.')) 237 | 238 | def get_data_selic_real(self): 239 | selic = self.acesso.cleanContent(self.req.content.decode('utf-8')) 240 | search = re.search(r'
([\d/]+)
', selic) 241 | if not search: 242 | raise AttributeNotFound 243 | return search.group(1) 244 | --------------------------------------------------------------------------------