Compartir tecnología

[Rastreador] Analizar datos rastreados

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Para analizar datos, además de la biblioteca BeautifulSoup anterior, existen dos métodos: expresiones regulares y Xpath.

1. Expresiones regulares

Las expresiones regulares (RE para abreviar) son herramientas que se utilizan para describir y hacer coincidir patrones de cadenas.

Se utiliza ampliamente en procesamiento de texto, validación de datos, búsqueda y reemplazo de texto y otros escenarios. Las expresiones regulares utilizan una sintaxis especial que permite la coincidencia de patrones complejos en cadenas.

Prueba de expresión regular:Prueba de expresión regular en línea

1. Metacaracteres de uso común

Metacaracteres: símbolos especiales con significados fijos. Cada metacarácter coincide solo con una cadena de forma predeterminada y no puede coincidir con caracteres de nueva línea.

MetacaracteresdescribirEjemplo
.Coincide con cualquier carácter excepto nuevas líneasa.b puede coincidira1bacb
wEmparejar letras, números o guiones bajosw+ fósforohelloworld_123
sCoincide con cualquier carácter de espacio en blancos+ Coincide con espacios, tabulaciones, etc.
dNúmeros coincidentesd+ fósforo123456
nCoincide con un carácter de nueva líneahellonworld Coincidir con el carácter de nueva línea
tcoincidir con un carácter de tabulaciónhellotworld coincidir con el carácter de la pestaña
^Coincide con el comienzo de una cadena^Hello fósforoHello cadena al principio
$Haga coincidir el final de la cuerdaWorld$ fósforoWorld final de la cuerda
WCoincide con caracteres que no son letras, ni dígitos ni guiones bajosW+ fósforo!@#$%^
DCoincidir caracteres no numéricosD+ fósforoabcXYZ
SCoincidir con caracteres que no sean espacios en blancoS+ fósforohelloworld123
`unB`Coincidir personajes a o personajeb
(...)Captura una expresión entre paréntesis, que representa un grupo.(abc) capturaabc
[...]Coincide con cualquier carácter entre corchetes[abc] fósforoab oc
[^...]Coincide con cualquier carácter que no esté entre corchetes[^abc] coincidir exceptoabc Cualquier personaje que no sea

2. Cuantificador

Cuantificador: controla el número de apariciones del metacarácter anterior.

cuantificadordescribir
*Repetir cero o más veces
+Repetir una o más veces
?Repetir cero o una vez
{n}repetir n veces
{n,}Repetir no más veces
{n,m}Repetir n a m veces

emparejamiento perezoso.*? : Combina la menor cantidad de personajes posible.Después de repetir los metacaracteres, agregue? Implementar coincidencias diferidas.
coincidencia codiciosa.* : Combina tantos personajes como sea posible. Los metacaracteres repetidos predeterminados son codiciosos.

emparejamiento perezoso

coincidencia codiciosa

3. Re módulo

Para procesar expresiones regulares en Python, puedes usar re módulo, este módulo proporciona un conjunto de funciones para buscar, hacer coincidir y manipular cadenas.

funcióndescribir
re.search(pattern, string, flags=0)Busque una cadena y devuelva el primer objeto coincidente; si no hay ninguna coincidencia, devuelva; None
re.match(pattern, string, flags=0)Haga coincidir el patrón desde el principio de la cadena; si la coincidencia es exitosa, devuelva el objeto coincidente; de ​​lo contrario, None
re.fullmatch(pattern, string, flags=0)Devuelve el objeto coincidente si toda la cadena coincide exactamente con el patrón; de lo contrario, devuelve None
re.findall(pattern, string, flags=0)Devuelve una lista de todas las coincidencias que no se superponen en una cadena
re.finditer(pattern, string, flags=0)Devuelve un iterador de todas las coincidencias que no se superponen en una cadena
re.sub(pattern, repl, string, count=0, flags=0)Reemplace todas las partes del patrón coincidente con la cadena de reemplazo, devolviendo la cadena reemplazada
re.split(pattern, string, maxsplit=0, flags=0)Divida la cadena según la coincidencia de patrones y devuelva la lista dividida
import re

# 示例文本
text = "在2024年,Python是最受欢迎的编程语言之一。Python 3.9版本在2020年发布。"

# 1. re.search() 搜索字符串,返回第一个匹配的对象
# 查找第一个数字序列
search_result = re.search(r'd+', text)
if search_result:
    print(f"re.search: 找到的第一个数字是 '{search_result.group()}',位置在 {search_result.start()}")  

# 2. re.match() 从字符串起始位置匹配模式
# 匹配字符串开头是否为 '在'
match_result = re.match(r'在', text)
if match_result:
    print(f"re.match: 匹配的字符串是 '{match_result.group()}',位于字符串的开始")

# 3. re.fullmatch() 整个字符串完全匹配模式
# 检查整个字符串是否只包含中文字符
fullmatch_result = re.fullmatch(r'[u4e00-u9fff]+', '在编程')
if fullmatch_result:
    print(f"re.fullmatch: 整个字符串完全匹配,匹配到的内容是 '{fullmatch_result.group()}'")  

# 4. re.findall() 返回字符串中所有非重叠匹配的列表
# 查找所有的数字序列
findall_result = re.findall(r'd+', text)
print(f"re.findall: 找到的所有数字序列是 {findall_result}") 

# 5. re.finditer() 返回字符串中所有非重叠匹配的迭代器
# 查找所有的数字序列,并逐一输出
finditer_result = re.finditer(r'd+', text)
for match in finditer_result:
    print(f"re.finditer: 找到的数字是 '{match.group()}',位置在 {match.start()}")  

# 6. re.sub() 用替换字符串替换匹配模式的所有部分
# 将所有数字替换为 '#'
sub_result = re.sub(r'd+', '#', text)
print(f"re.sub: 替换后的字符串是: {sub_result}") 

# 7. re.split() 根据模式匹配分割字符串
# 按照空白字符或标点分割字符串
split_result = re.split(r'[,。 ]+', text)
print(f"re.split: 分割后的字符串列表是: {split_result}") 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

imagen-20240608195856954

4. Rastrear películas de Douban

imagen-20240608200527961

de<li>A partir de la etiqueta, haga coincidir gradualmente la etiqueta que contiene el nombre de la película.<span class="title">etiqueta, use el modo no codicioso (.*?) coincide con cualquier carácter que pueda existir en el medio hasta que se encuentre el siguiente token explícito, utilizando un grupo de captura con nombre(?P<name>)Extrae la parte del título de la película.

Re expresión escrita:

<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>
  • 1

Código de rastreo:

import requests
import re
from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
}

for start_num in range(0, 250, 25):
    response = requests.get(f"https://movie.douban.com/top250?start={start_num}", headers=headers)
    # 拿到页面源代码
    html = response.text
    # 使用re解析数据
    obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>',re.S)
    # 开始匹配
    result = obj.finditer(html)
    # 打印结果
    for it in result:
        print(it.group('name'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2. XPatio

XPath es un lenguaje para buscar en documentos XML. Puede seleccionar nodos o conjuntos de nodos mediante expresiones de ruta. HTML es un subconjunto de XML.

Instale el módulo lxml: pip install lxml

1. Análisis XPath

Ⅰ. Selección de nodo.

símboloexplicar
/Seleccione desde el nodo raíz.
//Selecciona nodos en el documento a partir del nodo actual que coincide con la selección, independientemente de su posición.
.Seleccione el nodo actual.
..Selecciona el nodo principal del nodo actual.
@Seleccione propiedades.

Ⅱ. Expresión de ruta.

expresiónexplicar
/bookstore/bookSeleccione todos los subnodos de libros en el nodo de librería.
//bookSelecciona todos los nodos del libro en el documento, independientemente de su posición.
bookstore/book[1]Seleccione el primer nodo secundario del libro debajo del nodo de la librería.
//title[@lang]Seleccione todos los nodos de título con atributo lang.
//title[@lang='en']Seleccione todos los nodos de título cuyo atributo de idioma sea 'en'.

Ⅲ. Funciones de uso común.

  • text(): Seleccione el texto del elemento.
  • @attr: Seleccione el atributo del elemento.
  • contains(): Determinar la relación de inclusión.
  • starts-with(): El comienzo del juicio.
from lxml import etree

html_content = '''
<html>
  <body>
    <div class="movie">
      <span class="title">肖申克的救赎</span>
      <span class="title">The Shawshank Redemption</span>
    </div>
    <div class="movie">
      <span class="title">霸王别姬</span>
      <span class="title">Farewell My Concubine</span>
    </div>
  </body>
</html>
'''

# 解析HTML
tree = etree.HTML(html_content)

# 提取电影标题
titles_cn = tree.xpath('//div[@class="movie"]/span[@class="title"][1]/text()')
titles_en = tree.xpath('//div[@class="movie"]/span[@class="title"][2]/text()')

# 打印结果
for cn, en in zip(titles_cn, titles_en):
    print(f'中文标题: {cn}, 英文标题: {en}')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
//div[@class="movie"]/span[@class="title"][1]/text()
  • 1

//div[@class="movie"]: Seleccione todas las clases comomovieelemento div.

/span[@class="title"][1]: Seleccione la clase en cada div comotitleEl primer elemento de tramo.

/text(): obtiene el contenido de texto del elemento span.

//div[@class="movie"]/span[@class="title"][2]/text()
  • 1

Similar a la expresión anterior, pero se selecciona la clase en cada div.titleEl segundo elemento de tramo.

2. Rastrear películas de Douban

Douban

import requests
from lxml import etree

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
}

for start_num in range(0, 250, 25):
    response = requests.get(f"https://movie.douban.com/top250?start={start_num}", headers=headers)
    # 拿到页面源代码
    html = response.text
    # 使用lxml解析页面
    html = etree.HTML(html)
    # 提取电影名字
    titles = html.xpath('//*[@id="content"]/div/div[1]/ol/li/div/div[2]/div[1]/a/span[1]/text()')
    # 提取评分
    ratings = html.xpath('//*[@id="content"]/div/div[1]/ol/li/div/div[2]/div[2]/div/span[2]/text()')
    # 打印结果
    for title, rating in zip(titles, ratings):
        print(f"电影: {title} 评分: {rating}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20