2010-12-01 8 views
5

Estoy usando lxml en Python para analizar algo de HTML y quiero extraer todos los enlaces a las imágenes. La forma en que lo hago en este momento es:Python, XPath: Buscar todos los enlaces a las imágenes

//a[contains(@href,'.jpg') or contains(@href,'.jpeg') or ... (etc)] 

Hay un par de problemas con este enfoque:

  • usted tiene que enumerar todas las posibles extensiones de imagen en todos los casos (tanto "jpg" y " JPG "), cosa que no es elegante
  • en unas situaciones extrañas, el href puede contener .jpg algún lugar en el medio, no al final de la cadena

que quería utilizar expresiones regulares, pero falló:

//a[regx:match(@href,'.*\.(?:png|jpg|jpeg)')] 

Esto me devuelve todos los enlaces todo el tiempo ...

¿Alguien sabe la derecha, manera elegante de hacer esto o lo que está mal con mi enfoque expresión regular?

+0

Buena pregunta, +1. Vea mi respuesta para encontrar una solución a uno de sus problemas: encontrar @href que solo finaliza con una cadena dada. –

+0

Además de las otras respuestas que describen subcadenas, puede usar la función de conversión para conversión de mayúsculas y minúsculas. translate (@href, "EGIJFNP", "egijfnp") (todos los caracteres dentro de png, jpeg, gif). – yonran

+0

@yonran No sé si esta es una buena idea, porque alterará también el resto de la URL, no solo la extensión, y no quiero que –

Respuesta

2

En lugar de:

a[contains(@href,'.jpg')] 

Uso:

a[substring(@href, string-length(@href)-3)='.jpg'] 

(y el mismo patrón de expresión para las otras posibles finales).

La expresión anterior es el XPath 1.0 equivalente a la siguiente XPath 2.0 expresión:

a[ends-with(@href, '.jpg')] 
2

Utilice XPath para devolver todos los elementos <a> y utilice una comprensión de la lista Python para filtrar hasta aquellos que coincidan con su expresión regular.

+1

vaya con esta. Pero no responde por qué XPath no puede hacer regex ... – delnan

+0

Tal vez sea su sintaxis. Un google rápido sugiere 'fn: matches' en lugar de' regx: match'. –

1

Porque no hay garantía de que el enlace tenga una extensión de archivo, o que la extensión de archivo coincida con el contenido (URL .jpg que devuelve error HTML, por ejemplo) que limita sus opciones.

La única manera correcta de reunir todas las imágenes de un sitio sería obtener cada vínculo y consultarlo con una solicitud HEAD HTTP para averiguar qué tipo de contenido el servidor está enviando para ello. Si el tipo de contenido es imagen/(cualquier cosa) es una imagen, de lo contrario no lo es.

Sin embargo, es probable que raspar las URL de las extensiones de archivos comunes le proporcione el 99.9% de las imágenes. No es elegante, pero tampoco lo es la mayoría de HTML. Recomiendo encantarme conformarme con el 99.9% en este caso. El 0,1% extra no vale la pena.

0

Uso:

//a[@href[contains('|png|jpg|jpeg|', 
        concat('|', 
          substring-after(substring(.,string-legth()-4),'.'), 
          '|')]] 
2

lxml soporta expresiones regulares en EXSLT espacio de nombres:

from lxml import html 

# download & parse web page 
doc = html.parse('http://apod.nasa.gov/apod/astropix.html') 

# find the first <a href that ends with .png or .jpg or .jpeg ignoring case 
ns = {'re': "http://exslt.org/regular-expressions"} 
img_url = doc.xpath(r"//a[re:test(@href, '\.(?:png|jpg|jpeg)', 'i')]/@href", 
        namespaces=ns, smart_strings=False)[0] 
print(img_url) 
Cuestiones relacionadas