Expressões regulares

Expressões regulares Expressões regulares

Expressões regulareslink image 70

	
import re
Copy

Este caderno foi traduzido automaticamente para torná-lo acessível a mais pessoas, por favor me avise se você vir algum erro de digitação..

Métodoslink image 71

Localizarlink image 72

Com o método findall(), podemos encontrar todas as correspondências de um padrão em uma string.

	
import re
string = "Hola, soy un string"
print(re.findall("Hola, soy", string))
Copy
	
['Hola, soy']

Pesquisalink image 73

Mas se quisermos encontrar a posição em que um padrão está localizado, podemos usar o método search() para procurar um padrão em uma string. Esse método retorna um objeto Match se encontrar uma correspondência, caso contrário, retorna None.

	
print(re.search("soy", string))
Copy
	
<re.Match object; span=(6, 9), match='soy'>

Correspondêncialink image 74

Também podemos usar o método match() que procura o padrão no início da string.

	
print(re.match("Hola", string))
print(re.match("soy", string))
Copy
	
<re.Match object; span=(0, 4), match='Hola'>
None

Spanlink image 75

Se quisermos obter a posição da correspondência, podemos usar o método span() que retorna uma tupla com a posição inicial e final da correspondência.

	
print(re.match("Hola", string).span())
Copy
	
(0, 4)

Grupolink image 76

Sabendo a posição da correspondência, podemos usar o método group() para obter a substring que corresponde ao padrão.

	
print(re.match("Hola", string).group())
Copy
	
Hola

Também poderíamos usar o início e o fim da correspondência para criar uma fatia da cadeia de caracteres.

	
start, end = re.match("Hola", string).span()
print(string[start:end])
Copy
	
Hola

Separaçãolink image 77

Com o método split(), podemos dividir uma string em uma lista de substrings usando um padrão como separador.

	
split = re.split("soy", string)
print(split)
Copy
	
['Hola, ', ' un string']

A frase foi dividida em duas cadeias de caracteres usando "I am" como separador.

Sublink image 78

Com o método sub(), podemos substituir todas as correspondências de um padrão por outra substring.

	
sub = re.sub("soy", "eres", string)
print(sub)
Copy
	
Hola, eres un string

Ele substituiu todas as correspondências de "I am" por "you are".

Padrõeslink image 79

O caractere .link image 80

Com o caractere ., podemos pesquisar qualquer caractere; qualquer caractere em nossa string será encontrado.

	
string = "Hola, soy un string"
print(re.findall(".", string))
Copy
	
['H', 'o', 'l', 'a', ',', ' ', 's', 'o', 'y', ' ', 'u', 'n', ' ', 's', 't', 'r', 'i', 'n', 'g']

Se, por exemplo, quisermos sequências de dois caracteres, faremos a busca com dois .s em uma linha.

	
string1 = "Hola, soy un string"
string2 = "Hola, soy un string2"
print(re.findall("..", string1))
print(re.findall("..", string2))
Copy
	
['Ho', 'la', ', ', 'so', 'y ', 'un', ' s', 'tr', 'in']
['Ho', 'la', ', ', 'so', 'y ', 'un', ' s', 'tr', 'in', 'g2']

Como podemos ver, string1 tem um número ímpar de caracteres, de modo que o último g não é usado, mas string2 tem um número par de caracteres, de modo que todos os caracteres são usados.

Vamos analisar isso de outra forma: vamos alterar cada sequência de três caracteres para um símbolo $.

	
print(string1)
print(re.sub("...", "$ ", string1))
Copy
	
Hola, soy un string
$ $ $ $ $ $ g

Imprimi dois espaços após cada $ para que você possa ver a alteração, e você pode ver como o último caractere não o converte.

As classes predefinidas e construídaslink image 81

Dígitolink image 82

Se quisermos encontrar os dígitos, precisaremos usar d.

	
string = "Hola, soy un string con 123 digitos"
print(re.findall("d", string))
Copy
	
['1', '2', '3']

Como antes, se, por exemplo, quisermos dois dígitos, colocamos d duas vezes.

	
print(re.findall("dd", string))
Copy
	
['12']

Cartalink image 83

Se quisermos encontrar letras, precisamos usar w. Palavra significa todas as letras de a a z, de A a Z, números de 0 a 9 e o _.

	
string = "Hola, soy un_string con, 123 digitos"
print(re.findall("w", string))
Copy
	
['H', 'o', 'l', 'a', 's', 'o', 'y', 'u', 'n', '_', 's', 't', 'r', 'i', 'n', 'g', 'c', 'o', 'n', '1', '2', '3', 'd', 'i', 'g', 'i', 't', 'o', 's']

Como podemos ver, ele usa tudo, exceto os espaços e a vírgula.

Espaçoslink image 84

Se quisermos encontrar espaços, precisamos de "espaços".

	
string = "Hola, soy un_string con, 123 digitos"
print(re.sub("s", "*", string))
Copy
	
Hola,*soy*un_string*con,*123*digitos

As expressões regulares tratam as quebras de linha como espaços.

	
string = """Hola, soy un string
con un salto de línea"""
print(re.sub("s", "*", string))
Copy
	
Hola,*soy*un*string**con*un*salto*de*línea

Rankslink image 85

Se quisermos pesquisar um intervalo, usaremos [], por exemplo, se quisermos os números de 4 a 8, usaremos

	
string = "1234567890"
print(re.findall("[4-8]", string))
Copy
	
['4', '5', '6', '7', '8']

Podemos ampliar o intervalo de pesquisa

	
string = "1234567890"
print(re.findall("[2-57-9]", string))
Copy
	
['2', '3', '4', '5', '7', '8', '9']

Se também quisermos encontrar um caractere específico, colocaremos o caractere seguido de ``.

	
string = "1234567890."
print(re.findall("[2-57-9.]", string))
Copy
	
['2', '3', '4', '5', '7', '8', '9', '.']

Colchete [ e colchete ]link image 86

Como vimos, se quisermos encontrar intervalos, usamos [], mas e se quisermos encontrar apenas o [ ou o ]? Para isso, temos que usar [] e []`.

	
string = "[1234567890]"
print(re.findall("[", string))
print(re.findall("]", string))
Copy
	
['[']
[']']

Os delimitadores +, *, ?, `?link image 87

Star * (nenhum ou todos)link image 88

O delimitador * indica que você deseja pesquisar nenhum ou todos eles, e não um a um como antes.

	
string = "Hola, soy un string con 12 123 digitos"
print(re.findall("d", string))
print(re.findall("d*", string))
Copy
	
['1', '2', '1', '2', '3']
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '12', '', '123', '', '', '', '', '', '', '', '', '']

Como você pode ver, colocar o * encontrou todas as posições em que há zero caracteres ou todos os caracteres.

Plus + (um ou mais)link image 89

Com o delimitador +, você indica que deseja pesquisar um ou mais

	
string = "Hola, soy un string con 1 12 123 digitos"
print(re.findall("d+", string))
Copy
	
['1', '12', '123']

Opcional ? (zero ou um)link image 90

O delimitador ? indica que você deseja pesquisar zero ou um.

	
string = "Hola, soy un string con 1 12 123 digitos"
print(re.sub("d?", "-", string))
Copy
	
-H-o-l-a-,- -s-o-y- -u-n- -s-t-r-i-n-g- -c-o-n- -- --- ---- -d-i-g-i-t-o-s-

Contadoreslink image 91

Quando quisermos encontrar algo que apareça x vezes, usaremos os contadores entre chaves {}. Por exemplo, se quisermos encontrar uma sequência na qual haja pelo menos dois dígitos

	
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("d{2}", string))
Copy
	
['12', '12', '12', '34', '12', '34']

Como você pode ver, você encontrou as sequências 12 e 34.

Os contadores aceitam uma dimensão superior e inferior {{inf, sup}.

	
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("d{2,5}", string))
Copy
	
['12', '123', '1234', '1234']

Se nenhuma dimensão superior for definida, isso significa que você deseja pelo menos o número de elementos indicado, mas nenhum limite superior.

	
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("d{2,}", string))
Copy
	
['12', '123', '1234', '12345464168415641646451563416']

Se quisermos usar a notação de dimensão superior e inferior, mas quisermos um número fixo, teremos que colocar esse número em ambas as dimensões.

	
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("d{2,3}", string))
Copy
	
['12', '123', '123', '123', '454', '641', '684', '156', '416', '464', '515', '634', '16']

Classeslink image 92

Você pode criar classes usando colchetes []. Na verdade, vimos que isso era para intervalos, mas, depois de definir o que deseja dentro deles, você pode considerá-lo como uma classe e operar com o [].

Por exemplo, suponha que tenhamos um número de telefone, que pode ser fornecido de uma das seguintes maneiras

  • 666-66-66-66
  • 666-666-666
  • 666 666 666
  • 666 66 66 66
  • 666666666

Há muitas maneiras de fornecer um número, portanto, vamos ver como criar uma classe para definir o delimitador.

Primeiro, pediremos a ele que encontre todas as sequências de números em que haja pelo menos dois números.

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d{2,}", string1))
print(f"string2: {string2} -->", re.findall("d{2,}", string2))
print(f"string3: {string3} -->", re.findall("d{2,}", string3))
print(f"string4: {string4} -->", re.findall("d{2,}", string4))
print(f"string5: {string5} -->", re.findall("d{2,}", string5))
Copy
	
string1: 666-66-66-66 --> ['666', '66', '66', '66']
string2: 666-666-666 --> ['666', '666', '666']
string3: 666 66 66 66 --> ['666', '66', '66', '66']
string4: 666 666 666 --> ['666', '666', '666']
string5: 666666666 --> ['666666666']

Agora, definimos o separador a ser encontrado como um - ou um espaço.

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("[-s]", string1))
print(f"string2: {string2} -->", re.findall("[-s]", string2))
print(f"string3: {string3} -->", re.findall("[-s]", string3))
print(f"string4: {string4} -->", re.findall("[-s]", string4))
print(f"string5: {string5} -->", re.findall("[-s]", string5))
Copy
	
string1: 666-66-66-66 --> ['-', '-', '-']
string2: 666-666-666 --> ['-', '-']
string3: 666 66 66 66 --> [' ', ' ', ' ']
string4: 666 666 666 --> [' ', ' ']
string5: 666666666 --> []

Como você pode ver na última string, ela não foi encontrada, então adicionamos um ? para encontrar quando há zero ou um.

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("[-s]?", string1))
print(f"string2: {string2} -->", re.findall("[-s]?", string2))
print(f"string3: {string3} -->", re.findall("[-s]?", string3))
print(f"string4: {string4} -->", re.findall("[-s]?", string4))
print(f"string5: {string5} -->", re.findall("[-s]?", string5))
Copy
	
string1: 666-66-66-66 --> ['', '', '', '-', '', '', '-', '', '', '-', '', '', '']
string2: 666-666-666 --> ['', '', '', '-', '', '', '', '-', '', '', '', '']
string3: 666 66 66 66 --> ['', '', '', ' ', '', '', ' ', '', '', ' ', '', '', '']
string4: 666 666 666 --> ['', '', '', ' ', '', '', '', ' ', '', '', '', '']
string5: 666666666 --> ['', '', '', '', '', '', '', '', '', '']

Agora estamos procurando que tudo esteja junto

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string1))
print(f"string2: {string2} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string2))
print(f"string3: {string3} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string3))
print(f"string4: {string4} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string4))
print(f"string5: {string5} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string5))
Copy
	
string1: 666-66-66-66 --> ['666-66-66-66']
string2: 666-666-666 --> []
string3: 666 66 66 66 --> ['666 66 66 66']
string4: 666 666 666 --> []
string5: 666666666 --> ['666666666']

Como podemos ver em string2 e string4, ele não encontra nada. Definimos o filtro [\d{2,}[\s]? 4 vezes, ou seja, queremos uma sequência de pelo menos dois números, seguida por zero ou um hífen ou separador de espaço que se repita 4 vezes. Mas na última sequência não há necessidade do [\d{2,}[\s]?, pois ele nunca terminará um número com um espaço ou um hífen.

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string1))
print(f"string2: {string2} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string2))
print(f"string3: {string3} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string3))
print(f"string4: {string4} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string4))
print(f"string5: {string5} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string5))
Copy
	
string1: 666-66-66-66 --> ['666-66-66-66']
string2: 666-666-666 --> []
string3: 666 66 66 66 --> ['666 66 66 66']
string4: 666 666 666 --> []
string5: 666666666 --> ['666666666']

Ainda não foi encontrado para string2 e string4. Isso ocorre porque a última coisa no filtro é um d{2,}, ou seja, após o terceiro separador, esperamos pelo menos dois números, mas isso não acontece em string2 e string4, então colocamos o seguinte

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string1))
print(f"string2: {string2} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string2))
print(f"string3: {string3} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string3))
print(f"string4: {string4} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string4))
print(f"string5: {string5} -->", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string5))
Copy
	
string1: 666-66-66-66 --> ['666-66-66-66']
string2: 666-666-666 --> ['666-666-666']
string3: 666 66 66 66 --> ['666 66 66 66']
string4: 666 666 666 --> ['666 666 666']
string5: 666666666 --> ['666666666']

O delimitador ? como um delimitador rápidolink image 93

O exemplo acima pode ser filtrado usando d+?[- ].

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d+?[- ]", string1))
print(f"string2: {string2} -->", re.findall("d+?[- ]", string2))
print(f"string3: {string3} -->", re.findall("d+?[- ]", string3))
print(f"string4: {string4} -->", re.findall("d+?[- ]", string4))
print(f"string5: {string5} -->", re.findall("d+?[- ]", string5))
Copy
	
string1: 666-66-66-66 --> ['666-', '66-', '66-']
string2: 666-666-666 --> ['666-', '666-']
string3: 666 66 66 66 --> ['666 ', '66 ', '66 ']
string4: 666 666 666 --> ['666 ', '666 ']
string5: 666666666 --> []

Sem o delimitador ?, teríamos \d+[- ], o que significa uma sequência de um ou mais números seguidos por um espaço ou hífen. Mas o que o delimitador ? faz é tornar essa busca mais rápida

O negadorlink image 94

Anteriormente, vimos que com d encontramos dígitos, portanto, com D encontramos tudo o que não é dígito.

	
string1 = "E3s4t6e e1s2t3r5i6n7g8 t9i0e4n2e1 d4i5g7i9t0o5s2"
print(re.findall("D", string1))
Copy
	
['E', 's', 't', 'e', ' ', 'e', 's', 't', 'r', 'i', 'n', 'g', ' ', 't', 'i', 'e', 'n', 'e', ' ', 'd', 'i', 'g', 'i', 't', 'o', 's']

O mesmo vale para as letras: se você digitar W, ele encontrará tudo o que não for uma letra.

	
string1 = "Letras ab27_ no letras ,.:;´ç"
print(re.findall("W", string1))
Copy
	
[' ', ' ', ' ', ' ', ',', '.', ':', ';', '´']

Se colocarmos S, encontraremos tudo o que não for espaço

	
print(re.findall("S", string1))
Copy
	
['L', 'e', 't', 'r', 'a', 's', 'a', 'b', '2', '7', '_', 'n', 'o', 'l', 'e', 't', 'r', 'a', 's', ',', '.', ':', ';', '´', 'ç']

Mas, caso tenhamos uma classe ou outra coisa, podemos negá-la com ^.

	
string1 = "1234567890"
print(re.findall("[^5-9]", string1))
Copy
	
['1', '2', '3', '4', '0']

Voltando ao exemplo anterior dos números de telefone, podemos filtrá-los da seguinte forma

	
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string1))
print(f"string2: {string2} -->", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string2))
print(f"string3: {string3} -->", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string3))
print(f"string4: {string4} -->", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string4))
print(f"string5: {string5} -->", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string5))
string5 = "666 666 666"
Copy
	
string1: 666-66-66-66 --> ['666-66-66-66']
string2: 666-666-666 --> ['666-666-666']
string3: 666 66 66 66 --> ['666 66 66 66']
string4: 666 666 666 --> ['666 666 666']
string5: 666666666 --> ['666666666']

O que estamos fazendo é solicitar sequências de pelo menos dois dígitos seguidos de um ou nenhum não-dígito.

O início ^ e o final da linha $.link image 95

Com ^, podemos pesquisar o início de uma linha, por exemplo, se quisermos encontrar um dígito que esteja apenas no início de uma linha.

	
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("^d", string1))
print(re.findall("^d", string2))
Copy
	
[]
['2']

Como você pode ver, há apenas um dígito no início da linha em string2.

Da mesma forma, o final de uma linha pode ser encontrado com $. Se quisermos encontrar um dígito apenas no final de uma linha

	
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("d$", string1))
print(re.findall("d$", string2))
Copy
	
['1']
[]

Isso só ocorre em string1.

Exemplos práticoslink image 96

Registroslink image 97

Se no registro a seguir quisermos encontrar apenas os WARNs

	
log = """[LOG ENTRY] [ERROR] The system is unstable
[LOG ENTRY] [WARN] The system may be down
[LOG ENTRY] [WARN] Microsoft just bought Github
[LOG DATA] [LOG] Everything is OK
[LOG ENTRY] [LOG] [user:@beco] Logged in
[LOG ENTRY] [LOG] [user:@beco] Clicked here
[LOG DATA] [LOG] [user:@celismx] Did something
[LOG ENTRY] [LOG] [user:@beco] Rated the app
[LOG ENTRY] [LOG] [user:@beco] Logged out
[LOG LINE] [LOG] [user:@celismx] Logged in"""
result = re.findall("[LOG.*[WARN].*", log)
result
Copy
	
['[LOG ENTRY] [WARN] The system may be down',
'[LOG ENTRY] [WARN] Microsoft just bought Github']

Número de telefonelink image 98

Dentro de um número, podemos encontrar letras como e para ramal, # também para ramal ou p para fazer uma pausa se um computador ligar. Também podemos encontrar o + para indicar um prefixo de país e separadores como espaços, -, ., ., ., ., ., ., ., ., ., ., ..

	
tel = """555658
56-58-11
56.58.11
56.78-98
65 09 87
76y87r98
45y78-56
78.87 65
78 54-56
+521565811
58-11-11#246
55256048p123
55256048e123"""
result = re.findall("+?d{2,3}[^da-zA-Z\n]?d{2,3}[^da-zA-Z\n]?d{2,3}[#pe]?d*", tel)
result
Copy
	
['555658',
'56-58-11',
'56.58.11',
'56.78-98',
'65 09 87',
'78.87 65',
'78 54-56',
'+521565811',
'58-11-11#246',
'55256048p123',
'55256048e123']

Vamos explicar

  • +?: começando com o caractere + e contendo zero ou um
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • Em seguida, pode haver zero ou um caractere que não seja um dígito, nem uma letra de a a z, nem uma letra de A a Z, nem uma quebra de linha.
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • Em seguida, pode haver zero ou um caractere que não seja um dígito, nem uma letra de a a z, nem uma letra de A a Z, nem uma quebra de linha.
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • [#pe]?: então pode haver zero ou um caractere #, ou p, ou e.
  • Por fim, que haja zero ou todos os números.

URLslink image 99

	
urls = """url: https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx
url: http://instagram.com/p/blablablah
url: http://itam.mx/test
http://instagram.com/p/blablablah
https://www.vanguarsoft.com.ve
http://platzi.com
https://traetelo.net
https://traetelo.net/images archivo.jsp
url: https://subdominio.traetelo.net
url: https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx
url: http://instagram.com/p/blablablah
url: http://itam.mx/test
http://instagram.com/p/blablablah
https://www.google.com.co/
https://sub.dominio.de.alguien.com/archivo.html
https://en.wikipedia.org/wiki/.org
https://cdn-microsoft.org/image/seixo2t9sjl_22.jpg
https://hola.pizza
https://platzi.com/clases/1301-expresiones-regulares/11860-urls9102/ clase
https://api.giphy.com/v1/gifs/search?q=Rick and Morty&limit=10&api_key=DG3hItPp5HIRNC0nit3AOR7eQZAe
http://localhost:3000/something?color1=red&color2=blue
http://localhost:3000/display/post?size=small
http://localhost:3000/?name=satyam
http://localhost:3000/scanned?orderid=234
http://localhost:3000/getUsers?userId=12354411&name=Billy
http://localhost:3000/getUsers?userId=12354411
http://localhost:3000/search?city=Barcelona
www.sitiodeejemplo.net/pagina.php?nombredevalor1=valor1&nombredevalor2=valor2"""
result = re.findall("https?://[w-.]+.w{2,6}/?S*", urls)
result
Copy
	
['https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx',
'http://instagram.com/p/blablablah',
'http://itam.mx/test',
'http://instagram.com/p/blablablah',
'https://www.vanguarsoft.com.ve',
'http://platzi.com',
'https://traetelo.net',
'https://traetelo.net/images',
'https://subdominio.traetelo.net',
'https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx',
'http://instagram.com/p/blablablah',
'http://itam.mx/test',
'http://instagram.com/p/blablablah',
'https://www.google.com.co/',
'https://sub.dominio.de.alguien.com/archivo.html',
'https://en.wikipedia.org/wiki/.org',
'https://cdn-microsoft.org/image/seixo2t9sjl_22.jpg',
'https://hola.pizza',
'https://platzi.com/clases/1301-expresiones-regulares/11860-urls9102/',
'https://api.giphy.com/v1/gifs/search?q=Rick']

Vamos explicar

  • http: queremos que ele comece com http.
  • s?: Então pode ou não haver um s.
  • :\/: seguido por ://
  • `[+]: seguido de uma ou mais letras, traços ou pontos
  • Então, um ponto
  • w{2,6}: Entre 2 e 6 letras para o tld
  • \/?: seguido por zero ou um /
  • Nenhum ou tudo que não seja um espaço.

E-mailslink image 100

	
mails = """esto.es_un.mail@mail.com
esto.es_un.mail+complejo@mail.com
dominio.com
rodrigo.jimenez@yahoo.com.mx
ruben@starbucks.com
esto_no$es_email@dominio.com
no_se_de_internet3@hotmail.com"""
result = re.findall("[w._]{5,30}+?[w._]{0,10}@[w.-]{2,}.w{2,6}", mails)
result
Copy
	
['esto.es_un.mail@mail.com',
'esto.es_un.mail+complejo@mail.com',
'rodrigo.jimenez@yahoo.com.mx',
'ruben@starbucks.com',
'es_email@dominio.com',
'no_se_de_internet3@hotmail.com']

Vamos explicar

  • {5,30}`: queremos que ele comece com um número entre 5 e 30 (que é o mínimo e o máximo que o gmail suporta) letras, pontos ou sublinhados.
  • Seguido por um zero ou um +.
  • {0,10}`: Então, entre 0 e 10 letras, pontos ou barras
  • @: O @: O @: O @: O @
  • [{2,}: Entre 2 e infinitas letras, pontos e hífens (domínio)
  • seguido de um '`.
  • w{2,6}: E, finalmente, entre 2 e 6 letras para o tld

Localizaçõeslink image 101

Há duas maneiras possíveis de fornecer locais, portanto, examinaremos ambas

	
loc = """-99.205646,19.429707,2275.10
-99.205581, 19.429652,2275.10
-99.204654,19.428952,2275.58"""
result = re.findall("-?d{1,3}.d{1,6},s?-?d{1,3}.d{1,6},.*", loc)
result
Copy
	
['-99.205646,19.429707,2275.10',
'-99.205581, 19.429652,2275.10',
'-99.204654,19.428952,2275.58']

Vamos explicar

  • Queremos que ele comece com zero ou um sinal de menos.
  • Seguido de um a três números
  • Então, um ponto
  • d{1,6}: Depois de um a seis números
  • ,: Then a ,: Then a ,: Then a ,: Then a ,: Then a ,
  • s?: Após zero ou um espaço
  • ``-?`: Zero ou um sinal de menos
  • ``: Então, entre um e três números
  • Então, um ponto
  • Seguido de um a seis números
  • ,: depois uma vírgula
  • Finalmente, nenhum ou todos os tipos de caracteres
	
loc = """-99 12' 34.08"W, 19 34' 56.98"N
-34 54' 32.00"E, -3 21' 67.00"S"""
result = re.findall("-?d{1,3}sd{1,2}'sd{1,2}.d{2,2}\"[WE],s?-?d{1,3}sd{1,2}'sd{1,2}.d{2,2}\"[SN]", loc)
result
Copy
	
['-99 12' 34.08"W, 19 34' 56.98"N', '-34 54' 32.00"E, -3 21' 67.00"S']
	
print(result[0])
print(result[1])
Copy
	
-99 12' 34.08"W, 19 34' 56.98"N
-34 54' 32.00"E, -3 21' 67.00"S

Vamos explicar

  • Queremos que ele comece com zero ou um sinal de menos.
  • Seguido de um a três números
  • s: Em seguida, um espaço
  • d{1,2}: Segmento de um a dois números
  • ': Then a ': Then a ': Then a ': Then a ': Then a '
  • Seguido de um espaço
  • ``: Então, entre um e dois números
  • Após um ponto
  • d{2,2}: seguido por dois números
  • ": then a ": then a ": then a ": then a ".
  • [WE]: Em seguida, a letra W ou a letra E.
  • ,: Após uma vírgula
  • Seguido por um zero ou um espaço
  • ``-?`: Então, zero ou um sinal de menos
  • ``: Então, entre um e três números
  • Seguido de um espaço
  • ``: Então, entre um e dois números
  • ': Then a ': After a '
  • s: Em seguida, um espaço
  • d{1,2}`: Então, entre um e dois números
  • seguido de um ponto final
  • d{2,2}: Então, dois números
  • ": Seguido por ".
  • [SN]: E, finalmente, a letra S ou a letra N.

Nomeslink image 102

	
nombres = """Camilo Sarmiento Gálvez
Alejandro Pliego Abasto
Milagros Reyes Japón
Samuel París Arrabal
Juan Pablo Tafalla
Axel Gálvez Velázquez
Óscar Montreal Aparicio
Jacobo Pozo Tassis
Guillermo Ordóñez Espiga
Eduardo Pousa Curbelo
Ivanna Bienvenida Kevin
Ada Tasis López
Luciana Sáenz García
Florencia Sainz Márquz
Catarina Cazalla Lombarda
Paloma Gallo Perro
Margarita Quesada Florez
Vicente Fox Quesada
Iris Graciani
Asunción Carballar
Constanza Muñoz
Manuel Andres García Márquez"""
result = re.findall("[A-ZÁÉÍÓÚ][a-záéíóú]+s[A-ZÁÉÍÓÚ][a-záéíóú]+s[A-ZÁÉÍÓÚ][a-záéíóú]+", nombres)
result
Copy
	
['Camilo Sarmiento Gálvez',
'Alejandro Pliego Abasto',
'Milagros Reyes Japón',
'Samuel París Arrabal',
'Juan Pablo Tafalla',
'Axel Gálvez Velázquez',
'Óscar Montreal Aparicio',
'Jacobo Pozo Tassis',
'Espiga Eduardo Pousa',
'Curbelo Ivanna Bienvenida',
'Kevin Ada Tasis',
'López Luciana Sáenz',
'García Florencia Sainz',
'Márquz Catarina Cazalla',
'Lombarda Paloma Gallo',
'Perro Margarita Quesada',
'Florez Vicente Fox',
'Quesada Iris Graciani',
'Asunción Carballar Constanza',
'Manuel Andres García']

Vamos explicar

  • [A-ZÁÉÍÓÚ]: queremos que ele comece com uma letra maiúscula, incluindo acentos.
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços
  • Seguido de um espaço
  • [A-ZÁÉÍÓÚ]: seguido de uma letra maiúscula, incluindo acentos
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços
  • Seguido de um espaço
  • [A-ZÁÉÍÓÚ]: seguido de uma letra maiúscula, incluindo acentos
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços

Pesquisar e substituirlink image 103

Faremos o download de um arquivo com vários filmes históricos.

	
# download file from url
import urllib.request
url = "https://static.platzi.com/media/tmp/class-files/github/moviedemo/moviedemo-master/movies.dat"
urllib.request.urlretrieve(url, "movies.dat")
Copy
	
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
Cell In[43], line 4
2 import urllib.request
3 url = "https://static.platzi.com/media/tmp/class-files/github/moviedemo/moviedemo-master/movies.dat"
----> 4 urllib.request.urlretrieve(url, "movies.dat")
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:241, in urlretrieve(url, filename, reporthook, data)
224 """
225 Retrieve a URL into a temporary location on disk.
226
(...)
237 data file as well as the resulting HTTPMessage object.
238 """
239 url_type, path = _splittype(url)
--> 241 with contextlib.closing(urlopen(url, data)) as fp:
242 headers = fp.info()
244 # Just return the local path and the "headers" for file://
245 # URLs. No sense in performing a copy unless requested.
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:216, in urlopen(url, data, timeout, cafile, capath, cadefault, context)
214 else:
215 opener = _opener
--> 216 return opener.open(url, data, timeout)
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:525, in OpenerDirector.open(self, fullurl, data, timeout)
523 for processor in self.process_response.get(protocol, []):
524 meth = getattr(processor, meth_name)
--> 525 response = meth(req, response)
527 return response
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:634, in HTTPErrorProcessor.http_response(self, request, response)
631 # According to RFC 2616, "2xx" code indicates that the client's
632 # request was successfully received, understood, and accepted.
633 if not (200 <= code < 300):
--> 634 response = self.parent.error(
635 'http', request, response, code, msg, hdrs)
637 return response
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:563, in OpenerDirector.error(self, proto, *args)
561 if http_err:
562 args = (dict, 'default', 'http_error_default') + orig_args
--> 563 return self._call_chain(*args)
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:496, in OpenerDirector._call_chain(self, chain, kind, meth_name, *args)
494 for handler in handlers:
495 func = getattr(handler, meth_name)
--> 496 result = func(*args)
497 if result is not None:
498 return result
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:643, in HTTPDefaultErrorHandler.http_error_default(self, req, fp, code, msg, hdrs)
642 def http_error_default(self, req, fp, code, msg, hdrs):
--> 643 raise HTTPError(req.full_url, code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden

Vamos imprimir as primeiras 10 linhas para analisá-las.

	
file = open("movies.dat", "r")
for i, line in enumerate(file):
print(line, end="")
if i == 10:
break
file.close()
Copy
	
1::Toy Story (1995)::Adventure|Animation|Children|Comedy|Fantasy
2::Jumanji (1995)::Adventure|Children|Fantasy
3::Grumpier Old Men (1995)::Comedy|Romance
4::Waiting to Exhale (1995)::Comedy|Drama|Romance
5::Father of the Bride Part II (1995)::Comedy
6::Heat (1995)::Action|Crime|Thriller
7::Sabrina (1995)::Comedy|Romance
8::Tom and Huck (1995)::Adventure|Children
9::Sudden Death (1995)::Action
10::GoldenEye (1995)::Action|Adventure|Thriller
11::American President, The (1995)::Comedy|Drama|Romance

Como você pode ver, temos um ID, seguido por ::, depois o nome do filme, entre parênteses o ano, seguido por :: e depois os gêneros separados por |.

Podemos fazer uma limpeza de arquivo muito fácil usando expressões regulares, as funções compile e match e o uso de agrupamento com parênteses. Ao agrupar, selecionamos as áreas do texto que queremos manter e, em seguida, trabalhamos com elas como quisermos.

	
pattern = re.compile(r"^d+::([ws:,().-'&¡!/¿?ÁÉÍÓÚáéíóú+*$#°'"[]@·]+)s((d{4,4}))::(.*)$")
file = open("movies.dat", "r")
file_filtered = open("movies.csv", "w")
file_filtered.write("title,year,genders ")
sep = ";;"
for line in file:
result = re.match(pattern, line)
if result:
file_filtered.write(f"{result.group(1)}{sep}{result.group(2)}{sep}{result.group(3)} ")
else:
print(line, end="")
file.close()
file_filtered.close()
Copy

Vejamos o que fizemos: primeiro, definimos um padrão com o seguinte:

  • ^: Queremos que ele comece com o início da linha.
  • Próximo um ou mais números
  • ::: Seguido por ::
  • `((([\¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡: esse é o primeiro agrupamento, procuramos qualquer palavra, espaço ou caractere entre colchetes que apareça uma ou mais vezes.
  • s: depois um espaço
  • `: O fechamento de um parêntese
  • (4,4})`: Aqui está o segundo agrupamento, estamos procurando por quatro números.
  • Após o fechamento de um parêntese
  • ::: Then ::
  • (.*): o terceiro agrupamento, qualquer caractere que não ocorra nenhuma ou todas as vezes
  • $: Por último, o final da linha

Dentro do for, analisamos linha por linha se o padrão que definimos foi encontrado e, se for encontrado, escrevemos os três padrões no csv separados por sep, que, no nosso caso, definimos como ;;. Esse separador foi definido porque há títulos de filmes que têm ,s.

Lemos o csv com o Pandas.

import pandas as pd
      df = pd.read_csv("movies.csv", sep=";;", engine="python")
      df.head()
      
Out[100]:
title,year,genders
Toy Story 1995 Adventure|Animation|Children|Comedy|Fantasy
Jumanji 1995 Adventure|Children|Fantasy
Grumpier Old Men 1995 Comedy|Romance
Waiting to Exhale 1995 Comedy|Drama|Romance
Father of the Bride Part II 1995 Comedy

Folha de dicaslink image 104

Aqui está um [cheatsheet] (https://cheatography.com/davechild/cheat-sheets/regular-expressions/pdf/) com vários padrões

davechild_regular-expressions

Continuar lendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

Você já conversou com um LLM e ele lhe respondeu algo que parece ter bebido café de máquina a noite toda? 😂 Isso é o que chamamos de alucinação no mundo dos LLMs! Mas não se preocupe, pois não é que seu modelo de linguagem esteja louco (embora às vezes possa parecer isso 🤪). A verdade é que os LLMs podem ser um pouco... criativos quando se trata de gerar texto. Mas graças ao DoLa, um método que usa camadas de contraste para melhorar a viabilidade dos LLMs, podemos evitar que nossos modelos de linguagem se transformem em escritores de ficção científica 😂. Nesta publicação, explicarei como o DoLa funciona e mostrarei um exemplo de código para que você possa entender melhor como tornar seus LLMs mais confiáveis e menos propensos a inventar histórias. Vamos salvar nossos LLMs da loucura e torná-los mais úteis! 🚀

Últimos posts -->

Você viu esses projetos?

Subtify

Subtify Subtify

Gerador de legendas para vídeos no idioma que você desejar. Além disso, coloca uma legenda de cor diferente para cada pessoa

Ver todos os projetos -->

Quer aplicar IA no seu projeto? Entre em contato!

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Ver todos os contêineres -->

Quer aplicar IA no seu projeto? Entre em contato!

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

Dataset com piadas em inglês

opus100

Dataset com traduções de inglês para espanhol

netflix_titles

Dataset com filmes e séries da Netflix

Ver mais datasets -->