Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

O código dá erro no telefone de nove dígitos {resolvido}

Olá pessoal, sobre este tema, procurei bastante e não encontrei nenhuma resposta clara, então, segui a dica dos instrutores e fui fuçar na documentação do Re, caso tenha curiosidade também, é possível acessar aqui. Bom, depois de testar algumas vezes creio ter conseguido uma resposta que, na minha situação, resolve.

Funciona com o seguinte padrão:

([0-9]{2,3}?)?([1-9]{2})([6-9])?([0-9]{4})([0-9]{4}$)

Este padrão se divide em 5 grupos, sendo:

  1. ([0-9]{2,3}?)? --> esta parte analisa os primeiros dígitos de uma forma que a documentação chama de non-greedy, basicamente ele tenta preencher o grupo com o menor numero possível de combinações, neste caso {2,3}?, ele força o 2, caso "sobre" um digito, completa com 3.
  2. ([1-9]{2}) --> Verificação simples de DDD
  3. ([6-9])? --> Verificação do 9º dígito, a '?' faz com que este campo não seja obrigatório, coloquei de [6-9] pois por padrão, celulares começam com estes dígitos, apesar de no Brasil estarmos utilizando apenas o dígito "9".
  4. ([0-9]{4}) --> Diz que o 4º grupo obrigatoriamente tem que ter 4 dígitos.
  5. ([0-9]{4})$ --> Por fim, temos esta expressão terminada em '$' que 'força' caber na expressão inteira, este sinal se faz necessário por causa da expressão do primeiro passo, se você não colocar seu padrão poderá ignorar o último dígito de um telefone, já que ele vai forçar o grupo 1 a ter 2 dígitos

Então é como se lêssemos de trás para frente, os últimos 4 dígitos estão forçados, ai temos mais 4 dígitos, então, verifica se existe um 9º dígito, estão, encaixa os 2 dígitos de DDD e por fim de 0, 2 ou 3 dígitos de DDI desde que seja a menor combinação possível.

Claro, sei que isso não resolve tudo, como por exemplo, e se meu cliente enviar 1 dígito a mais? Bom, pensando nisso, eu testei algo que creio não ser o método mais pythonico que existe, mas estou só começando, então, resolve... Para validar a quantidade de dígitos eu utilizei um if, da seguinte forma:

import re

texto = "155 45 988764 1343 "
numero = texto.replace(' ', '') #Usei esta parte apenas para poder copiar diversos números da internet e não precisar ficar formatando manualmente, osb.: não sei porque o método strip() não rolou.
print(numero) # Printa 15545987641343

padrao = "([0-9]{2,3}?)?([1-9]{2})([6-9])?([0-9]{4})([0-9]{4}$)"

if len(numero) in range(6, 15):
    telefone = re.search(padrao, numero)

E para verificar os valores podemos usar:

print(telefone.group(1)) # Printa 155
print(telefone.group(2)) # Printa 45
print(telefone.group(3)) # Printa 9, quando número não tem 9º dígito aqui retorna None
print(telefone.group(4)) # Printa 8764
print(telefone.group(5)) # Printa 1343

É importante ter em mente que o grupo 3 pode voltar None em caso de números celular sem 9º dígito, só reforçando...

Então, para uso na aula precisamos de mais 1 if para verificar se o grupo 3 é None:

cod = telefone.group  # Só para facilitar a vida e diminuir o tamanho a fstring
if telefone.group(3) is None:
    print(f"+{cod(1)} ({cod(2)}) {cod(4)}-{cod(5)}")
else:
    print(f"+{cod(1)} ({cod(2)}) {cod(3)}{cod(4)}-{cod(5)}")

Bom, assim eu resolvi esta situação, espero ter ajudado e que me ajudem a validar mais números, testei vários DDIs, mas o mundo é grande pakas e é osso saber se vai dar match sempre.

Como foi meu primeiro post, espero ter formatado minimamente bem. Vlws, flws povo.

1 resposta
solução!

mais uma coisa que acho interessante passar, como ficou essa bagunça na classe?

    import re

class Telefones_br:
    def __init__(self, telefone):
        if self.__validatelefone(telefone):
            self.__numero = telefone
        else:
            raise ValueError("Número inválido, deve ser um celular ou fixo com DDD")

    def __validatelefone(self, telefone):
        if len(telefone) in range(6, 15):
            padrao = "([0-9]{2,3}?)?([1-9]{2})([6-9])?([0-9]{4})([0-9]{4}$)"
            resposta = re.findall(padrao, telefone)
            if resposta:
                return True
            else:
                return False
        else:
            return False

@property
def __numero_formatado(self):
    padrao = "([0-9]{2,3}?)?([1-9]{2})([6-9])?([0-9]{4})([0-9]{4}$)"
    telefone = re.search(padrao, self.__numero)
    return telefone.group  # Só para facilitar a vida e diminuir o tamanho a fstring

def __str__(self):
    cod = self.__numero_formatado
    if not cod(1) and not cod(3):
        return f"({cod(2)}) {cod(4)}-{cod(5)}"
    elif not cod(1):
        return f"({cod(2)}) {cod(3)}{cod(4)}-{cod(5)}"
    elif not cod(3):
        return f"+{cod(1)} ({cod(2)}) {cod(4)}-{cod(5)}"
    else:
        return f"+{cod(1)} ({cod(2)}) {cod(3)}{cod(4)}-{cod(5)}"

Para deixar com uma cara mais pythonica, ainda estou me desenvolvendo... Fiz esse monte de possibilidade por chatisse mesmo, queria todas as variações, fixo BR, celular BR, Fixo DDI e Celular DDI Obs.: já testei bastante e funfa.