From 3ccb2e4ce196c77a0282d1ab5bf23924c3fd8a86 Mon Sep 17 00:00:00 2001 From: Gaws21 Date: Sun, 3 Oct 2021 14:47:59 -0300 Subject: [PATCH 1/6] v1 bot_busca_localidade_e_faixa_de_cep --- README.txt | 8 ++ bot_busca_localidade_e_faixa_de_cep.py | 153 +++++++++++++++++++++++++ requeriments.txt | 7 ++ 3 files changed, 168 insertions(+) create mode 100644 README.txt create mode 100644 bot_busca_localidade_e_faixa_de_cep.py create mode 100644 requeriments.txt diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..5839408 --- /dev/null +++ b/README.txt @@ -0,0 +1,8 @@ +PROCEDIMENTOS PARA TESTAR O SCRIPT: + +-- TENHA INSTALADO UMA VERSÃO DO PYTHON 3 COM VIRTUALENV; +-- CRIE UMA PASTA COM AMBIENTE VIRTUAL; +-- CLONE O REPOSITÓRIO PARA SUA MAQUINA LOCAL; +-- INSTALE AS DEPENDÊNCIAS (ARQUIVO DE REQUERIMENTS.TXT); +-- EXECUTE O COMANDO python bot_busca_localidade_e_faixa_de_cep.py; +-- APÓS EXECUÇÃO, DEVEM EXISTIR DOIS ARQUIVOS - faixas_cep_SP.txt & faixas_cep_RJ.txt. \ No newline at end of file diff --git a/bot_busca_localidade_e_faixa_de_cep.py b/bot_busca_localidade_e_faixa_de_cep.py new file mode 100644 index 0000000..8b5e709 --- /dev/null +++ b/bot_busca_localidade_e_faixa_de_cep.py @@ -0,0 +1,153 @@ +from bs4 import BeautifulSoup as bs +import requests +import json +import os +import logging + +os.system("cls") + +def request(UF): + """ + Essa função tem a responsabilidade de executar um método post no endereço da url. + Já que o intuito é apenas para a url específica, não houve intenção de exigir a declaração + desse parâmetro na chamada da função. + Para assegurar o parse de uma estrutura previsível, foi utilizado como User-Agent o navegador firefox + na versão 5. Conforme informações de header abaixo. + """ + + #informações de cabeçalho + header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'} + + #Dados necessário para o post. Também é possível especificar a cidade + #Adicionando uma segunda segunda chave de nome Localidade. + #Ex: dados_post = {'UF':'SP','Localidade':'sao paulo'} + dados_post = {'UF':UF} + try: + r = requests.post("https://www2.correios.com.br/sistemas/buscacep/resultadoBuscaFaixaCEP.cfm", data=dados_post, headers=header) + html_parser = bs(r.content, 'html.parser') + except TypeError: + print("Passe como parâmetro uma sigla de estado válida.") + except: + print("Não foi possível fazer a requisição. Status diferente de 200. Status:{status}".format(status=r.status_code)) + + return html_parser + +def retornar_tabela(html_parser): + """ + Essa função tem a resposabilidade de buscar todas as tabelas do html que + sejam da classe tmptabela. + Retorno: Lista de todas as tabelas que satisfaçam os requisitos mencionados. + """ + try: + html_find_all_table = html_parser.find_all("table", class_='tmptabela') + except: + print("Não foi possível fazer o find_all por table e class tmptabela. Reveja os parâmetros de busca.") + + return html_find_all_table + +def retornar_uf(html_find_all_table): + """ + Essa função tem a resposabilidade de capturar a sigla da estado/unidade federativa + na qual fizemos a busca. + + Como existem 2 tabela de classe tmptabela. A primeira tabela, de index 0, é a tabela que se encontra + a sigla da UF. + """ + try: + #html_find_all_table é um objeto do tipo ... + #o métrodo itera e retorna as tags filhas como objetos do tipo ... ou ... + #como os objetos do tipo... não trazem informações pertinentes elas são despresadas. + tag_table_children = [linha for linha in html_find_all_table[0].children if linha.__class__.__name__!='NavigableString'] + + #Em cada linha (objeto do tipo ...) filtrados por todas tags td (célula da tabela) + tag_tb = [td_tag.find_all('td') for td_tag in tag_table_children] + + #o atributo string retorna o nome da tag/celula selecionada. + UF = tag_tb[1][0].string + return UF + except (UnboundLocalError, IndexError) as e: + print(\ + "Não foi possível iterar sobre o objeto tag ou a lista está vazia. \n\ +Reveja o tipo e o tamanho do parâmetro de entrada") + + +def retornar_json(html_find_all_table, UF): + + """ + Essa função tem a resposabilidade de capturar as linhas da segunda tabela. + Na primeira list comprehensions, apenas os objetos do tipo ... são extraídos. + Os objetos NavigableString não contém as informações de localidade e faixa de cep. + """ + try: + #retona todas as tags filhas da tabela + tag_table_children = [linha for linha in html_find_all_table[1].children if linha.__class__.__name__!='NavigableString'] + #retona uma lista de todas as tags td (células) contradas nas tags filhas (linhas das tabela) + tag_tb = [td_tag.find_all('td') for td_tag in tag_table_children] + + #armazena cada cojunto localidade e faixa de cep como um dicionário em uma lista. + #OBS: lstrip() foi acionado para remover um espaço em branco presente em todos registros + #de faixa de cep. + obj_estado_cep_lista = [\ + {"localidade":tab_tb_string[0].string,\ + "faixa_de_cep":tab_tb_string[1].string.lstrip()} \ + for tab_tb_string in tag_tb if len(tab_tb_string)!=0] + + obj_estado_cep_Lista_unica = {elemento_estado_cep["localidade"]:elemento_estado_cep \ + for elemento_estado_cep in obj_estado_cep_lista}.values() + #dicionário que será convertido em json + dict_obj_cidade_cep = {} + + #Valor inicial do id + id = 1 + + #UF recebe a UF retornada pela função .... + ID_UF = UF + + #itera sobre a lista dos objetos {localidade:estado,faixa_de_cep: cep_inicial a cep_final} + for elemento_estado_cep_unico in obj_estado_cep_Lista_unica: + + #o ID é concatenado com a sigla para formar uma chave composta única identificadora localidade + dict_obj_cidade_cep[ID_UF+str(id)] = elemento_estado_cep_unico + + #o id é incremental em 1 + id+=1 + + #cria o json exigido como requisito + #o argumento indet=4 formata o json com espaçamento 4 + #ensure_ascii mantém os caracteres látinos pós dump + json_final = json.dumps(dict_obj_cidade_cep, indent=4, ensure_ascii=False) + + #retorna o json + return json_final + except (UnboundLocalError, IndexError) as e: + print(\ + "Não foi possível iterar sobre o objeto tag, lista está vazia ou sigla inválida. \n\ +Reveja o tipo e o tamanho dos parâmetros de entrada") + +def gravar_json(path, file_name, obj_json): + with open(path+file_name, mode='w', encoding='utf-8') as open_json: + open_json.write(obj_json) + + +# --------------------------- BUSCA PARA SP --------------------- +request_SP = request('SP') +tabelas = retornar_tabela(request_SP) +ID_UF = retornar_uf(tabelas) +obj_json_final = retornar_json(tabelas, ID_UF) +print(obj_json_final) +gravar_json(r'.\\',"faixas_cep_SP.txt",obj_json_final) + +# --------------------------- BUSCA PARA RJ ----------------------- +request_SP = request('RJ') +tabelas = retornar_tabela(request_SP) +ID_UF = retornar_uf(tabelas) +obj_json_final = retornar_json(tabelas, ID_UF) +print(obj_json_final) +gravar_json(r'.\\',"faixas_cep_RJ.txt",obj_json_final) + +# --------------------------- BUSCA VAZIA - TESTE ------------------ +# request_SP = request(1.2) +# tabelas = retorna_tabela(request_SP) +# ID_UF = retorna_uf(tabelas) +# obj_json_final = retorna_json(tabelas, ID_UF) +# print(obj_json_final) diff --git a/requeriments.txt b/requeriments.txt new file mode 100644 index 0000000..383da80 --- /dev/null +++ b/requeriments.txt @@ -0,0 +1,7 @@ +beautifulsoup4==4.10.0 +certifi==2021.5.30 +charset-normalizer==2.0.6 +idna==3.2 +requests==2.26.0 +soupsieve==2.2.1 +urllib3==1.26.7 From 3ec602828124a1d3cec4ea3840e1a88ce6a23999 Mon Sep 17 00:00:00 2001 From: Gaws21 Date: Mon, 4 Oct 2021 13:10:27 -0300 Subject: [PATCH 2/6] add arquivo de test --- test_busca_localidade_e_faixa_de_cep.py | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test_busca_localidade_e_faixa_de_cep.py diff --git a/test_busca_localidade_e_faixa_de_cep.py b/test_busca_localidade_e_faixa_de_cep.py new file mode 100644 index 0000000..1483ca6 --- /dev/null +++ b/test_busca_localidade_e_faixa_de_cep.py @@ -0,0 +1,30 @@ +import pytest +from bs4 import BeautifulSoup as bs + +from bot_busca_localidade_e_faixa_de_cep import * +def test_request(): + header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'} + dados_post = {'UF':'SP'} + r = requests.post("https://www2.correios.com.br/sistemas/buscacep/resultadoBuscaFaixaCEP.cfm", data=dados_post, headers=header) + assert r.status_code == 200 + +tipo_bs4_element_resultset = 'bs4.element.ResultSet()' +def test_retornar_tabela(): + request_SP = request('SP') + tabelas = retornar_tabela(request_SP) + assert (tabelas.__class__.__name__) =='ResultSet' + +def test_retornar_UF(): + request_SP = request('SP') + tabelas = retornar_tabela(request_SP) + print(type(tabelas)) + ID_UF = retornar_uf(tabelas) + assert ID_UF == 'SP' + +def test_retornar_json_final(): + request_SP = request('SP') + tabelas = retornar_tabela(request_SP) + print(type(tabelas)) + ID_UF = retornar_uf(tabelas) + obj_json_final = retornar_json(tabelas, ID_UF) + assert len(obj_json_final) != 0 From a9cdc37062f10b1b14c842ec68de408ea3452385 Mon Sep 17 00:00:00 2001 From: Gaws21 Date: Mon, 4 Oct 2021 13:15:40 -0300 Subject: [PATCH 3/6] add pytest requeriments --- requeriments.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requeriments.txt b/requeriments.txt index 383da80..67d9796 100644 --- a/requeriments.txt +++ b/requeriments.txt @@ -5,3 +5,4 @@ idna==3.2 requests==2.26.0 soupsieve==2.2.1 urllib3==1.26.7 +pytest==6.2.5 From 6371a6931f4861880c12951e5fc16c594d60a085 Mon Sep 17 00:00:00 2001 From: Gaws21 <47149231+Gaws21@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:01:34 -0300 Subject: [PATCH 4/6] Delete README.md --- README.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 53a4644..0000000 --- a/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Jobs - -A list of jobs available at Neoway - -# Datapirates - -* [Challenge 1](datapirates/challenge.md) -* [Challenge 2](datapirates/challengePirates.md) From c0d39bd3dbeab86939218a0bebddd23ab2099472 Mon Sep 17 00:00:00 2001 From: Gaws21 Date: Tue, 5 Oct 2021 23:38:39 -0300 Subject: [PATCH 5/6] =?UTF-8?q?corre=C3=A7=C3=B5es=20-=20coment=C3=A1rios?= =?UTF-8?q?=20e=20docstrings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.txt | 20 ++++-- bot_busca_localidade_e_faixa_de_cep.py | 90 ++++++++++++++----------- test_busca_localidade_e_faixa_de_cep.py | 5 -- 3 files changed, 62 insertions(+), 53 deletions(-) diff --git a/README.txt b/README.txt index 5839408..e0793c2 100644 --- a/README.txt +++ b/README.txt @@ -1,8 +1,14 @@ -PROCEDIMENTOS PARA TESTAR O SCRIPT: +Procedimentos para executar o script: --- TENHA INSTALADO UMA VERSÃO DO PYTHON 3 COM VIRTUALENV; --- CRIE UMA PASTA COM AMBIENTE VIRTUAL; --- CLONE O REPOSITÓRIO PARA SUA MAQUINA LOCAL; --- INSTALE AS DEPENDÊNCIAS (ARQUIVO DE REQUERIMENTS.TXT); --- EXECUTE O COMANDO python bot_busca_localidade_e_faixa_de_cep.py; --- APÓS EXECUÇÃO, DEVEM EXISTIR DOIS ARQUIVOS - faixas_cep_SP.txt & faixas_cep_RJ.txt. \ No newline at end of file +-- Tenha instalado uma versão do python 3 com virtualenv; +-- Crie uma pasta para o ambiente virtual; +-- Clone o repositório para sua máquina local; +-- Instale as dependências (arquivo de requeriments.txt); +-- Execute o comando python bot_busca_localidade_e_faixa_de_cep.py; +-- Após execução, devem existir dois arquivos - faixas_cep_SP.txt & faixas_cep_RJ.txt. + +Procedimentos para testar o script: +-- Instalado o pytest, execute o comando pytest. +-- Automaticamente as funções no arquivo +test_busca_localidade_e_faixa_de_cep.py serão executadas. +-- A cobertura dos testes será informada na tela. \ No newline at end of file diff --git a/bot_busca_localidade_e_faixa_de_cep.py b/bot_busca_localidade_e_faixa_de_cep.py index 8b5e709..ac33c84 100644 --- a/bot_busca_localidade_e_faixa_de_cep.py +++ b/bot_busca_localidade_e_faixa_de_cep.py @@ -2,8 +2,8 @@ import requests import json import os -import logging +#clear de degug os.system("cls") def request(UF): @@ -11,25 +11,27 @@ def request(UF): Essa função tem a responsabilidade de executar um método post no endereço da url. Já que o intuito é apenas para a url específica, não houve intenção de exigir a declaração desse parâmetro na chamada da função. - Para assegurar o parse de uma estrutura previsível, foi utilizado como User-Agent o navegador firefox + Para assegurar o parse de uma estrutura previsível, foi utilizado como User-Agent o navegador Firefox na versão 5. Conforme informações de header abaixo. """ - - #informações de cabeçalho + #Informações de cabeçalho header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'} - #Dados necessário para o post. Também é possível especificar a cidade - #Adicionando uma segunda segunda chave de nome Localidade. + #Dados necessários para o post. Também é possível especificar a cidade + #adicionando uma segunda chave de nome localidade. #Ex: dados_post = {'UF':'SP','Localidade':'sao paulo'} dados_post = {'UF':UF} + try: - r = requests.post("https://www2.correios.com.br/sistemas/buscacep/resultadoBuscaFaixaCEP.cfm", data=dados_post, headers=header) - html_parser = bs(r.content, 'html.parser') + #Faz a request + r = requests.post("https://www2.correios.com.br/sistemas/buscacep/resultadoBuscaFaixaCEP.cfm", data=dados_post, headers=header) except TypeError: print("Passe como parâmetro uma sigla de estado válida.") except: - print("Não foi possível fazer a requisição. Status diferente de 200. Status:{status}".format(status=r.status_code)) - + print("Não foi possível fazer a requisição. Status diferente de 200. Status: {status}".format(status=r.status_code)) + + #retorna um objeto bs4.BeautifulSoup com a estrutura do HTML do response. + html_parser = bs(r.content, 'html.parser') return html_parser def retornar_tabela(html_parser): @@ -40,9 +42,10 @@ def retornar_tabela(html_parser): """ try: html_find_all_table = html_parser.find_all("table", class_='tmptabela') + except: print("Não foi possível fazer o find_all por table e class tmptabela. Reveja os parâmetros de busca.") - + return html_find_all_table def retornar_uf(html_find_all_table): @@ -50,41 +53,42 @@ def retornar_uf(html_find_all_table): Essa função tem a resposabilidade de capturar a sigla da estado/unidade federativa na qual fizemos a busca. - Como existem 2 tabela de classe tmptabela. A primeira tabela, de index 0, é a tabela que se encontra + Como existem 2 tabelas de classe tmptabela. A primeira tabela, de index 0, é a tabela que se encontra a sigla da UF. """ try: - #html_find_all_table é um objeto do tipo ... - #o métrodo itera e retorna as tags filhas como objetos do tipo ... ou ... - #como os objetos do tipo... não trazem informações pertinentes elas são despresadas. + #html_find_all_table é um objeto do tipo bs4.element.ResultSet + #o método children itera e retorna as tags filhas como objetos do tipo bs4.element.Tag ou NavigableString + #como os objetos do tipo NavigableString não trazem informações pertinentes elas são despresadas. tag_table_children = [linha for linha in html_find_all_table[0].children if linha.__class__.__name__!='NavigableString'] - #Em cada linha (objeto do tipo ...) filtrados por todas tags td (célula da tabela) + #Em cada linha (objeto do tipo bs4.element.ResultSet) filtramos por todas tags td (célula da tabela) tag_tb = [td_tag.find_all('td') for td_tag in tag_table_children] - - #o atributo string retorna o nome da tag/celula selecionada. + + #O atributo string retorna o nome da tag/célula selecionada. UF = tag_tb[1][0].string - return UF + except (UnboundLocalError, IndexError) as e: print(\ "Não foi possível iterar sobre o objeto tag ou a lista está vazia. \n\ -Reveja o tipo e o tamanho do parâmetro de entrada") +Reveja o tipo e o tamanho do parâmetro de entrada.") + return UF def retornar_json(html_find_all_table, UF): - """ Essa função tem a resposabilidade de capturar as linhas da segunda tabela. - Na primeira list comprehensions, apenas os objetos do tipo ... são extraídos. + Na primeira list comprehensions, apenas os objetos do tipo bs4.element.Tag são extraídos. Os objetos NavigableString não contém as informações de localidade e faixa de cep. """ try: - #retona todas as tags filhas da tabela + #Retona todas as tags filhas da tabela tag_table_children = [linha for linha in html_find_all_table[1].children if linha.__class__.__name__!='NavigableString'] - #retona uma lista de todas as tags td (células) contradas nas tags filhas (linhas das tabela) + + #Retona uma lista de todas as tags td (células) encontradas nas tags filhas (linhas da tabela) tag_tb = [td_tag.find_all('td') for td_tag in tag_table_children] - #armazena cada cojunto localidade e faixa de cep como um dicionário em uma lista. + #Armazena cada conjunto localidade e faixa de cep como um dicionário em uma lista. #OBS: lstrip() foi acionado para remover um espaço em branco presente em todos registros #de faixa de cep. obj_estado_cep_lista = [\ @@ -94,58 +98,62 @@ def retornar_json(html_find_all_table, UF): obj_estado_cep_Lista_unica = {elemento_estado_cep["localidade"]:elemento_estado_cep \ for elemento_estado_cep in obj_estado_cep_lista}.values() - #dicionário que será convertido em json + + #Dicionário que será convertido em json dict_obj_cidade_cep = {} #Valor inicial do id id = 1 - #UF recebe a UF retornada pela função .... + #UF recebe a UF retornada pela função retornar_uf ID_UF = UF - #itera sobre a lista dos objetos {localidade:estado,faixa_de_cep: cep_inicial a cep_final} + #Itera sobre a lista dos objetos {localidade:estado,faixa_de_cep: cep_inicial a cep_final} for elemento_estado_cep_unico in obj_estado_cep_Lista_unica: - #o ID é concatenado com a sigla para formar uma chave composta única identificadora localidade + #O ID é concatenado com a sigla para formar uma chave composta única identificadora de localidade dict_obj_cidade_cep[ID_UF+str(id)] = elemento_estado_cep_unico - #o id é incremental em 1 + #O id é incrementado em 1 id+=1 - #cria o json exigido como requisito - #o argumento indet=4 formata o json com espaçamento 4 - #ensure_ascii mantém os caracteres látinos pós dump + #Cria o json exigido como requisito. + #O argumento indet=4 formata o json com espaçamento 4 e + #ensure_ascii mantém os caracteres látinos pós dump. json_final = json.dumps(dict_obj_cidade_cep, indent=4, ensure_ascii=False) - #retorna o json - return json_final except (UnboundLocalError, IndexError) as e: print(\ "Não foi possível iterar sobre o objeto tag, lista está vazia ou sigla inválida. \n\ -Reveja o tipo e o tamanho dos parâmetros de entrada") +Reveja o tipo e o tamanho dos parâmetros de entrada.") + + #Retorna o json + return json_final def gravar_json(path, file_name, obj_json): + """ + Essa função tem a resposabilidade de gravar as informações do objeto json + em um arquivo texto com encoding utf-8, conforme requisito exigido. + """ with open(path+file_name, mode='w', encoding='utf-8') as open_json: open_json.write(obj_json) -# --------------------------- BUSCA PARA SP --------------------- +#--------------------------- BUSCA PARA SP --------------------- request_SP = request('SP') tabelas = retornar_tabela(request_SP) ID_UF = retornar_uf(tabelas) obj_json_final = retornar_json(tabelas, ID_UF) -print(obj_json_final) gravar_json(r'.\\',"faixas_cep_SP.txt",obj_json_final) -# --------------------------- BUSCA PARA RJ ----------------------- +#--------------------------- BUSCA PARA RJ ----------------------- request_SP = request('RJ') tabelas = retornar_tabela(request_SP) ID_UF = retornar_uf(tabelas) obj_json_final = retornar_json(tabelas, ID_UF) -print(obj_json_final) gravar_json(r'.\\',"faixas_cep_RJ.txt",obj_json_final) -# --------------------------- BUSCA VAZIA - TESTE ------------------ +#--------------------------- BUSCA VAZIA - TESTE ------------------ # request_SP = request(1.2) # tabelas = retorna_tabela(request_SP) # ID_UF = retorna_uf(tabelas) diff --git a/test_busca_localidade_e_faixa_de_cep.py b/test_busca_localidade_e_faixa_de_cep.py index 1483ca6..823c710 100644 --- a/test_busca_localidade_e_faixa_de_cep.py +++ b/test_busca_localidade_e_faixa_de_cep.py @@ -1,6 +1,3 @@ -import pytest -from bs4 import BeautifulSoup as bs - from bot_busca_localidade_e_faixa_de_cep import * def test_request(): header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'} @@ -17,14 +14,12 @@ def test_retornar_tabela(): def test_retornar_UF(): request_SP = request('SP') tabelas = retornar_tabela(request_SP) - print(type(tabelas)) ID_UF = retornar_uf(tabelas) assert ID_UF == 'SP' def test_retornar_json_final(): request_SP = request('SP') tabelas = retornar_tabela(request_SP) - print(type(tabelas)) ID_UF = retornar_uf(tabelas) obj_json_final = retornar_json(tabelas, ID_UF) assert len(obj_json_final) != 0 From ce2e196ebec3f532430f66174c749af367b3bb60 Mon Sep 17 00:00:00 2001 From: Gaws21 <47149231+Gaws21@users.noreply.github.com> Date: Tue, 5 Oct 2021 23:42:40 -0300 Subject: [PATCH 6/6] =?UTF-8?q?corre=C3=A7=C3=B5es=20-=20coment=C3=A1rios?= =?UTF-8?q?=20e=20docstrings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot_busca_localidade_e_faixa_de_cep.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot_busca_localidade_e_faixa_de_cep.py b/bot_busca_localidade_e_faixa_de_cep.py index ac33c84..fae118c 100644 --- a/bot_busca_localidade_e_faixa_de_cep.py +++ b/bot_busca_localidade_e_faixa_de_cep.py @@ -3,7 +3,7 @@ import json import os -#clear de degug +#clear de debug os.system("cls") def request(UF):