Aprendizaje de reptiles - (2) Expresiones regulares

Tabla de contenido

1. Introducción a las reglas comunes de coincidencia

 2. Métodos de coincidencia comúnmente utilizados

1. partido

2.buscar

3.encontrar todo

4.sub

5. compilar

3. Combate real de casos básicos de rastreadores.


1. Introducción a las reglas comunes de coincidencia

Reglas de coincidencia de uso común para expresiones regulares (consulte el sitio web de aprendizaje): Expresiones regulares - Gramática | Tutorial para principiantes

 2. Métodos de coincidencia comúnmente utilizados

1. partido

En el método de coincidencia, el primer parámetro se pasa en la expresión regular y el segundo parámetro es la cadena que se debe comparar.

El método de coincidencia intentará hacer coincidir la expresión regular desde la 'posición inicial' de la cadena, y si coincide, devolverá el resultado de una coincidencia exitosa; si no coincide, devolverá Ninguno. Los ejemplos son los siguientes:

import re
content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content)) #查看字符串的长度
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)
#result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)  #匹配所有字符
print(result)
print(result.group())  #返回匹配结果
print(result.span())   #输出范围

resultado de la operación:

41 
<re.Coincidir objeto; span=(0, 25), match='Hola 123 4567 Mundo_Este'> 
Hola 123 4567 Mundo_Este 
(0, 25)
  • coincidir con el objetivo

Para extraer parte de un texto, puede usar corchetes () para encerrar la subcadena que desea extraer. () en realidad marca las posiciones inicial y final de una subexpresión. Cada subexpresión marcada corresponde a cada grupo a su vez. Llame al método de grupo para pasar el índice del grupo para obtener el resultado de la extracción. El ejemplo es el siguiente:

import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^Hello\s(\d+)\sWorld',content)
print(result) 
print(result.group())  #输出完整的匹配结果
print(result.group(1)) #输出第一个被()包围的匹配结果
print(result.span())

resultado de la operación:

<re.Coincidir objeto; span=(0, 19), match='Hola 1234567 Mundo'> 
Hola 1234567 Mundo 
1234567 
(0, 19)
  • partido universal

Debido a la complejidad de la expresión regular anterior, siempre que haya un carácter de paquete vacío, debe coincidir con \s, y si hay un número, debe coincidir con \d. Cuando hay muchos contenidos coincidentes, este tipo de carga de trabajo es relativamente grande. De hecho, puede usar la coincidencia universal ".*", donde "." puede coincidir con cualquier carácter y "*" significa coincidir infinitamente con el carácter anterior, y la combinación de los dos puede coincidir con cualquier carácter. Siguiendo el ejemplo anterior, use ".*" para reescribir la expresión regular:

import re
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('^Hello.*Demo$',content)
print(result) 
print(result.group())  #输出完整的匹配结果
print(result.span())

resultado de la operación:

<re.Coincidir objeto; span=(0, 41), match='Hola 123 4567 Mundo_Esta es una demostración Regex'> 
Hola 123 4567 Mundo_Esta es una demostración Regex 
(0, 41)
  • Codiciosos vs no codiciosos
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*(\d+).*Demo$',content)
print(result) 
print(result.group(1))

resultado de la operación:

<re.Coincidir objeto; span=(0, 40), match='Hola 1234567 Mundo_Esta es una demostración Regex'> 
7

Se puede ver que bajo la coincidencia codiciosa, solo se obtiene el número 7. Debido a que en la coincidencia codiciosa, ".* " coincidirá con tantos caracteres como sea posible, y ".* " va seguido de \d+, es decir, al menos un número, y no se especifican números específicos, así que ".* "intente Es posible hacer coincidir varios números para que coincidan con 123456, dejando solo un número 7 que cumpla la condición, por lo que el contenido final es solo el número 7.

Obviamente, esto a veces nos traerá el mismo contenido, y algunos contenidos faltarán inexplicablemente. A continuación, compare la coincidencia no codiciosa y vea cómo funcionan las dos:

import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^He.*?(\d+).*?Demo$',content)
print(result) 
print(result.group(1))

resultado de la operación:

<re.Coincidir objeto; span=(0, 40), match='Hola 1234567 Mundo_Esta es una demostración Regex'> 
1234567

Se puede ver que bajo coincidencias no codiciosas, se pueden obtener 1234567 cadenas enteras de números. A diferencia de la coincidencia codiciosa, la coincidencia no codiciosa consiste en hacer coincidir la menor cantidad de caracteres posible. En las aplicaciones prácticas, la coincidencia no codiciosa debe usarse tanto como sea posible para evitar el problema de perder resultados de coincidencia.

Sin embargo, si lo que coincide es el contenido al final de la cadena, es mejor usar la coincidencia codiciosa ".* ", porque coincidirá con la mayor cantidad de contenido posible para que coincida con el contenido al final. Y ".*?", la coincidencia no codiciosa coincide con la menor cantidad de contenido posible, los ejemplos específicos son los siguientes:

import re
content = 'Hello 1234567 World_This is a Regex Demo'
result1 = re.match('^He.*?a\s(.*?)',content)
result2 = re.match('^He.*?a\s(.*)',content)
print('result1(非贪婪匹配)',result1.group(1))
print('result2(贪婪匹配)',result2.group(1))

resultado de la operación:

result1 (coincidencia no codiciosa) 
result2 (coincidencia codiciosa) Demostración Regex
  • modificador

re.I: hacer que coincidan mayúsculas y minúsculas

re.L: Realice la coincidencia de reconocimiento localizado (consciente de lo local)

re.M: coincidencia multilínea, afecta a ^ y $

re.S: haga coincidir todos los caracteres, incluidos los caracteres de nueva línea

re.U: analiza los caracteres de acuerdo con el juego de caracteres Unicode. Esta bandera afecta a \w, \W, \b y \B

re.X: esta bandera puede brindarle un formato más flexible, de modo que las expresiones regulares se pueden escribir de manera más fácil de entender

Cuando hay un carácter de nueva línea en la cadena, si coincide con lo anterior, se informará un error:

import re
content = '''Hello 1234567 World_This
is a Regex Demo
'''
result = re.match('^He.*?(\d+).*?Demo$',content)
print(result.group(1))
-------------------------------------------------- ------------------------- 
AttributeError Traceback (última llamada más reciente) 
~\AppData\Local\Temp/ipykernel_448/501554157.py en <módulo> 
      4 ''' 
      5 resultado = re.match('^He.*?(\d+).*?Demo$',content) 
----> 6 print(result.group(1)) 

AttributeError: 'NoneType' el objeto no tiene atributo 'grupo'

El resultado de la operación anterior informa un error, es decir, la expresión regular no coincide con la cadena, el resultado devuelto es Ninguno y se llama al método de grupo, por lo que se genera AttributeError

Dado que .*?coincide con cualquier carácter que no sea un carácter de nueva línea, la coincidencia falla porque se encuentra un carácter de nueva línea. Y solo agregue un modificador re.S para corregir el error

import re
content = '''Hello 1234567 World_This
is a Regex Demo
'''
result = re.match('^He.*?(\d+).*?Demo$',content,re.S)
print(result.group(1))

resultado de la operación:

1234567
  • partido de escape

Si la cadena de destino contiene caracteres que no sean caracteres de nueva línea, como ., puede agregar una barra invertida "\" delante de ella para lograr una coincidencia. Los ejemplos son los siguientes:

import re
content = '(百度)www.baidu.com'
result = re.match('\(百度\)www\.baidu\.com',content)
print(result.group())

resultado de la operación:

(Baidu) www.baidu.com

2.buscar

En el método de coincidencia anterior, debido a que este método comienza a coincidir desde el principio de la cadena, significa que una vez que el principio no coincida, la coincidencia completa fallará. El método de coincidencia debe tener en cuenta el contenido al comienzo de la cadena de destino al usarlo, por lo que no es conveniente para la coincidencia

El método de búsqueda escanea toda la cadena en busca de una coincidencia y devuelve la primera coincidencia exitosa. Es decir, la expresión regular puede ser parte de la cadena y no hay necesidad de pensar en cómo el método de coincidencia puede coincidir con el principio de la cadena. Al hacer coincidir, el método de búsqueda escanea la cadena comenzando con cada carácter hasta que encuentra la primera cadena coincidente y luego devuelve el contenido coincidente; si no se encuentra ninguna cadena coincidente después del escaneo, devuelve Ninguno. Cambie el método de coincidencia del código anterior al método de búsqueda, de la siguiente manera:

import re
content = '''Hello 1234567 World_This
is a Regex Demo
'''
result = re.search('He.*?(\d+).*?Demo',content,re.S)
print(result)
print(result.group(1))

resultado de la operación:

<re.Coincidir objeto; span=(0, 40), match='Hola 1234567 Mundo_Esta\es una demostración Regex'> 
1234567

Para la conveniencia de hacer coincidir, se recomienda usar el método de búsqueda tanto como sea posible, y luego usar la búsqueda para escribir varios ejemplos de expresiones regulares para realizar la extracción de información correspondiente:

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>'''
import re
result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S)
if result:
    print(result.group(1),result.group(2))

resultado de la operación:

Los eventos pasados ​​de Qi Qin siguen el viento

Como se puede ver en los resultados, este es el hipervínculo dentro del nodo li cuya clase está activa y contiene el título de la canción y el cantante. ¿Qué sucede si se elimina el activo? Vuelva a escribir el código de la siguiente manera:

import re
result = re.search('<li.*?singer="(.*?)">(.*?)</a>',html,re.S)
if result:
    print(result.group(1),result.group(2))

resultado de la operación:

Ren Xianqi Canghai se ríe

Después de eliminar la etiqueta activa, comience a buscar desde el principio de la cadena. En este momento, el nodo calificado se convierte en el segundo nodo li y los siguientes ya no coinciden, por lo que el resultado de la ejecución cambia. Estas dos coincidencias usan re.S, de modo que .*?

import re
result = re.search('<li.*?singer="(.*?)">(.*?)</a>',html)
if result:
    print(result.group(1),result.group(2))

resultado de la operación:

más allá de los días de gloria

Después de eliminar re.S, el resultado de la coincidencia se convierte en el contenido del cuarto nodo li, porque tanto el segundo como el tercer nodo li contienen caracteres de nueva línea, pero el cuarto nodo li no contiene caracteres de nueva línea, por lo que la coincidencia es exitosa.

3.encontrar todo

El método de búsqueda anterior, que devuelve la primera cadena que coincide con la expresión regular. Pero si desea obtener todas las cadenas que coincidan con la expresión regular, puede usar el método findall

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>'''
results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
print(type(results),results)
for result in results:
    print(result)  #输出位元组
    print(result[0],result[1],result[2])  #输出字符串

resultado de la operación:

<clase 'lista'> [('/2.mp3', 'Ren Xianqi', 'Una risa del mar'), ('/3.mp3', 'Qi Qin', 'El pasado sigue al viento') , ('/4 .mp3', 'más allá', 'Años gloriosos'), ('/5.mp3', 'Kelly Chen', 'Bloc de notas'), ('/6.mp3', 'Teresa Teng', 'Espero que la gente dure mucho' )] 
('/2.mp3', 'Ren Xianqi', 'Una risa en el mar') 
/2.mp3 Ren Xianqi en Una risa en el mar 
('/3.mp3', 'Qi Qin', 'El pasado sigue al viento') 
/3.mp3 El pasado de Qi y Qin con el viento 
('/4.mp3', 'más allá', 'Años de gloria') 
/4.mp3 Más allá de los años de gloria 
(' /5.mp3', 'Kelly Chen', 'Bloc de notas') 
/5.mp3 Bloc de notas de Kelly Chen 
('/6.mp3', 'Teresa Teng', 'Te deseo mucho tiempo') 
/6.mp3 Teresa Teng te deseo mucho tiempo

Se puede ver a partir de los resultados que el resultado devuelto al reemplazar el método de búsqueda con el método findall es un tipo de lista, y cada grupo de contenido debe obtenerse a su vez a través del recorrido. En general, si solo desea obtener la primera cadena coincidente, puede usar el método de búsqueda; si necesita extraer varios contenidos, use el método findall

4.sub

Además de usar expresiones regulares para extraer información, también puede usarlo para modificar información de texto. Por ejemplo, si desea eliminar sus números de una cadena de texto, sería demasiado engorroso usar el método de reemplazo. En este momento, puede usar el método sub para lograrlo. El primer parámetro se pasa al parámetro regular. expresión para que coincida con la información que debe modificarse, y el segundo parámetro se pasa para ser reemplazado. Contenido, el tercer parámetro es la cadena original. Introduzca el ejemplo a continuación:

import re
content = "121fef342dkjdsd87f7hiud3334"
content = re.sub('\d+','',content)
print(content)

resultado de la operación:

fefdkjdsdfhiud

5. compilar

compile puede compilar cadenas regulares en objetos de expresión regular para su reutilización en coincidencias posteriores. Los ejemplos son los siguientes:

import re
content1 = '2022/7/23晴'
content2 = '2022/7/24小雨'
content3 = '2022/7/25雷阵雨'
pattern = re.compile('\d{4}/\d{1}/\d{2}')
result1 = re.sub(pattern,'',content1)
result2 = re.sub(pattern,'',content2)
result3 = re.sub(pattern,'',content3)
print(result1,result2,result3)

3. Combate real de casos básicos de rastreadores.

La URL rastreada es: Douban Reading y el contenido rastreado es: hipervínculo, título del libro, autor, fecha de publicación

import re
import requests
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
content = requests.get('https://book.douban.com/',headers = headers).text  
pattern = re.compile('<li.*?cover">.*?href="(.*?)".*?title="(.*?)".*?more-meta">.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>',re.S)
results = re.findall(pattern,content)
for result in results:
    url,name,author,date=result
    author = re.sub('\s','',author)
    year = re.sub('\s','',year)
    print(url,name,author,date)

La eficiencia del rastreo de contenido de páginas web con expresiones regulares será relativamente baja y será más conveniente continuar aprendiendo bibliotecas como pyquery y beautifulsoup en el futuro.

Supongo que te gusta

Origin blog.csdn.net/weixin_52024937/article/details/125960094
Recomendado
Clasificación