2
respostas

Match está retornando sempre falso

Oi pessoal, tudo bem?

Estou tentando implementar meu código com as validações de startwith e endswith, conforme foi proposto como desafio do módulo 3. Ambos funcionaram perfeitamente.

No entanto, no módulo 4, passei a enfrentar problemas para conseguir fazer o código passar pela regex da url de forma que o código sempre passa como inválido pela condição do "match" e retorna o seu ValueError correspondente.

O trecho abaixo foi como eu construi o regex e sua validação. Somente para validar a condição verdadeira e ver o código passando pela validação, construí o regex exatamente como na URL, mas mesmo assim ele retorna o ValueError:

As outras validações do método, contemplando as funções startwith, endswith e também a validação da url estão contempladas no método:

    def valida_url(self):
        if not self.url:
            raise ValueError("A URL está vazia")

        if not (self.get_url_base().startswith('http://') or self.get_url_base().startswith('https://')):
            self.url = 'https://' + self.url
        if not self.get_url_base().endswith('/cambio'):
            raise ValueError("Não está na página de câmbio")

        regex_url = '(https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar)'
        match_url = re.compile(regex_url)
        match = match_url.match(self.url)
        if not match:
            raise ValueError ('Padrão de URL não é válido!')

E aqui meu código completo. Mais uma vez, na chamada da URL eu passei a url fielmente como na regex para que eu pudesse ver a situação do caminho feliz, mas mesmo assim retorna o ValueError. No final eu tento trazer o valor dos parâmetros da URL separadamente.

import re

class ExtratorURL:
    def __init__(self, url):
        self.url = self.sanitiza_url(url)
        print('A URL examinada é:\n', self.url)
        self.valida_url()
    def sanitiza_url(self, url):
        if type(url) == str:
            return url.strip()
        else:
            return ""
    def valida_url(self):
        if not self.url:
            raise ValueError("A URL está vazia")

        if not (self.get_url_base().startswith('http://') or self.get_url_base().startswith('https://')):
            self.url = 'https://' + self.url
        if not self.get_url_base().endswith('/cambio'):
            raise ValueError("Não está na página de câmbio")

        regex_url = '(https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar)'
        match_url = re.compile(regex_url)
        match = match_url.match(self.url)
        if not match:
            raise ValueError ('Padrão de URL não é válido!')


    def get_url_base(self):
        procura_url_parametros = self.url.find('?')
        seleciona_url_base = self.url[:procura_url_parametros]
        return seleciona_url_base
    def get_url_parametros(self):
        procura_url_parametros = self.url.find('?')
        posicao_inicial_parametro = procura_url_parametros + 1
        seleciona_url_parametros = self.url[posicao_inicial_parametro :]
        return seleciona_url_parametros

    def get_valor_parametros(self, valor_parametro):

        procura_url_parametros = self.get_url_parametros().find(valor_parametro)
        posicao_inicial_parametro = procura_url_parametros + len(valor_parametro) + 1
        procura_e_comercial = self.get_url_parametros().find('&', posicao_inicial_parametro)
        if procura_e_comercial == -1:
            valor = self.get_url_parametros()[posicao_inicial_parametro :]
        else:
            valor = self.get_url_parametros()[posicao_inicial_parametro : procura_e_comercial]
        print('O valor da variável {} é:\n{}' .format(valor_parametro, valor.title()))
        return valor

url_teste = ExtratorURL("https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar")


valor = url_teste.get_valor_parametros("quantidade")
valor2 = url_teste.get_valor_parametros("moedaOrigem")
valor3 = url_teste.get_valor_parametros("moedaDestino")

O retorno com o ValueError da URL:

Traceback (most recent call last):
  File "C:\Users\rafael.franco\PycharmProjects\pythonProject3\extrator_url.py", line 51, in <module>
    url_teste = ExtratorURL("https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar")
  File "C:\Users\rafael.franco\PycharmProjects\pythonProject3\extrator_url.py", line 7, in __init__
    self.valida_url()
  File "C:\Users\rafael.franco\PycharmProjects\pythonProject3\extrator_url.py", line 26, in valida_url
    raise ValueError ('Padrão de URL não é válido!')
ValueError: Padrão de URL não é válido!
A URL examinada é:
 https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar

Alguém consegue me ajudar onde eu posso estar errando? Não queria avançar no curso sem ter isso resolvido e concretizado meu aprendizado.

2 respostas

Olá, Rafael! Tudo bem?

Entendo que você está tendo problemas com o método match da biblioteca re do Python. O método match procura por uma correspondência no início da string. Se a correspondência não for encontrada no início da string, ele retornará None, mesmo que a string contenha a expressão regular em algum outro lugar.

Pelo que vejo no seu código, você está tentando validar uma URL exata com o método match, que é a seguinte: 'https://www.bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar'

Porém, acredito que o seu objetivo seja validar qualquer URL que siga o mesmo padrão, e não apenas essa URL específica. Nesse caso, a expressão regular precisa ser mais genérica.

A expressão regular que você está usando é muito específica, pois está tentando validar uma URL exata. Se você deseja validar qualquer URL que siga o mesmo padrão, você pode usar uma expressão regular mais genérica, como a seguinte:

regex_url = r'https://www\.bytebank\.com/cambio\?quantidade=\d+&moedaOrigem=\w+&moedaDestino=\w+'

Nesta expressão regular:

  • \d+ corresponde a um ou mais dígitos.
  • \w+ corresponde a uma ou mais letras.

Assim, a expressão regular irá validar qualquer URL que siga o mesmo padrão, independentemente dos valores específicos de quantidade, moedaOrigem e moedaDestino.

Espero ter ajudado e bons estudos!

Olá, Renan. Tudo bem? Deu certo aqui, mas fiz um complemento. Como eu ainda quero que o "http://www" ou "https://" possam ser entradas omitidas pelo usuário, eu defini elas como opcionais na minha regex. Complementando com a sua sugestão, ficou assim:

 regex_url = re.compile(r'(http(s)?://)?(www.)?bytebank\.com/cambio\?quantidade=\d+&moedaOrigem=\w+&moedaDestino=\w+')
        match_url = regex_url.match(self.url)

Agora, tenho uma outra dúvida e uma pergunta. Será que conseguiria me ajudar?

A dúvida é simples: Pra que serve o parâmetro r' na regex? Eu procurei em alguns dicionários aqui, mas as explicações não estão muito claras.

E a dúvida:

Eu tentei implementar no meu método de regex uma validação para verificar a existência do "http://" ou o "https://" na url. E caso esses valores não sejam encontrados, o próprio código deveria completá-los. Foi assim que pensei:

        regex_url = re.compile(r'(http(s)?://)?(www.)?bytebank\.com/cambio\?quantidade=\d+&moedaOrigem=\w+&moedaDestino=\w+')
        match_url = regex_url.match(self.url)
        if not match_url:
            raise ValueError('Padrão de URL não é válido!')

        if not re.match(r'^(http://|https://)', self.get_url_base()):
            self.url = re.sub(r'^.*?//', 'https://', self.url)
            print(self.url) #print para verificar se o código está chegando aqui
            return self.url

Porém, fiz o teste removendo o http:// para ver se ele faria o ajuste automaticamente, mas não está funcionando. Mesmo o código passando por esse trecho (veja que eu dei "#print para verificar se o código está chegando aqui"), a validação não está ocorrendo.

O que será que estou errando?

Lá vai o código completo pra tentar ajudar:

import re

class ExtratorURL:
    def __init__(self, url):
        self.url = self.sanitiza_url(url)
        print('A URL examinada é:\n', self.url)
        self.valida_url()
    def sanitiza_url(self, url):
        if type(url) == str:
            return url.strip()
        else:
            return ""
    def valida_url(self):

        if not self.url:
            raise ValueError("A URL está vazia")

        if not self.get_url_base().endswith('/cambio'):
            raise ValueError("Não está na página de câmbio")

        regex_url = re.compile(r'(http(s)?://)?(www.)?bytebank\.com/cambio\?quantidade=\d+&moedaOrigem=\w+&moedaDestino=\w+')
        match_url = regex_url.match(self.url)
        if not match_url:
            raise ValueError('Padrão de URL não é válido!')

        if not re.match(r'^(http://|https://)', self.get_url_base()):
            self.url = re.sub(r'^.*?//', 'https://', self.url)
            print(self.url)
            return self.url


    def get_url_base(self):
        procura_url_parametros = self.url.find('?')
        seleciona_url_base = self.url[:procura_url_parametros]
        return seleciona_url_base
    def get_url_parametros(self):
        procura_url_parametros = self.url.find('?')
        posicao_inicial_parametro = procura_url_parametros + 1
        seleciona_url_parametros = self.url[posicao_inicial_parametro :]
        return seleciona_url_parametros

    def get_valor_parametros(self, valor_parametro):

        procura_url_parametros = self.get_url_parametros().find(valor_parametro)
        posicao_inicial_parametro = procura_url_parametros + len(valor_parametro) + 1
        procura_e_comercial = self.get_url_parametros().find('&', posicao_inicial_parametro)
        if procura_e_comercial == -1:
            valor = self.get_url_parametros()[posicao_inicial_parametro :]
        else:
            valor = self.get_url_parametros()[posicao_inicial_parametro : procura_e_comercial]
        print('O valor da variável {} é:\n{}' .format(valor_parametro, valor.title()))
        return valor

    def __len__(self):
        return len(self.url)

    def __str__(self):
        return print(" URL completa: {} \n URL base: {} \n Parâmetros: {}" .format(self.url, self.get_url_base(), self.get_url_parametros()))

    def __eq__(self, other):
        return self.url == other.url

url = "bytebank.com/cambio?quantidade=200&moedaOrigem=dolar&moedaDestino=real"
url_parametros = ExtratorURL(url)
moeda_origem = url_parametros.get_valor_parametros('moedaOrigem')
moeda_destino = url_parametros.get_valor_parametros('moedaDestino')
quantidade = url_parametros.get_valor_parametros('quantidade')

valor_dolar = 5.50

if moeda_origem == 'real' and moeda_destino == 'dolar':
    conversao = int(quantidade)/valor_dolar
elif moeda_origem == 'dolar' and moeda_destino == 'real':
    conversao = int(quantidade) * valor_dolar
else:
    print('Conversão não está disponível no momento')

conversao_moeda = print("Valor convertido de {} para {} é de: {}" .format(moeda_origem, moeda_destino, conversao))