2011-05-04 25 views
13

Duplicar posible:
Beautiful Soup cannot find a CSS class if the object has other classes, tooBeautifulSoup y búsqueda por clase de

estoy usando BeautifulSoup encontrar tables en el código HTML. El problema con el que me estoy encontrando actualmente es el uso de espacios en el atributo class. Si mi HTML lee <html><table class="wikitable sortable">blah</table></html>, me parece que no puede extraerlo con la siguiente (donde iba a ser capaz de encontrar tables tanto con wikipedia y wikipedia sortable para la class):

BeautifulSoup(html).findAll(attrs={'class':re.compile("wikitable(sortable)?")}) 

Esto encontrará la mesa si mi HTML es solo <html><table class="wikitable">blah</table></html> sin embargo. Del mismo modo, he intentado usar "wikitable sortable" en mi expresión regular, y eso tampoco coincidirá. ¿Algunas ideas?

Respuesta

24

El partido patrón también fallará si wikitable aparece tras otra clase CSS, como en class="something wikitable other", por lo que si desea que todas las tablas cuyo atributo de clase contiene la clase wikitable, se necesita un patrón que acepta más posibilidades:

html = '''<html><table class="sortable wikitable other">blah</table> 
<table class="wikitable sortable">blah</table> 
<table class="wikitable"><blah></table></html>''' 

tree = BeautifulSoup(html) 
for node in tree.findAll(attrs={'class': re.compile(r".*\bwikitable\b.*")}): 
    print node 

Resultado:

<table class="sortable wikitable other">blah</table> 
<table class="wikitable sortable">blah</table> 
<table class="wikitable"><blah></blah></table> 

Sólo para que conste, no uso BeautifulSoup, y prefieren utilizar lxml, como otros han mencionado.

+2

Solo como una actualización, la última versión de BeautifulSoup (bs4) maneja esto mucho más elegantemente: http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-by-css-class – Eli

8

Una de las cosas que hace lxml mejor que BeautifulSoup es el apoyo a la selección de clase CSS-como adecuada (o incluso apoya full css selectors si desea utilizarlos)

import lxml.html 

html = """<html> 
<body> 
<div class="bread butter"></div> 
<div class="bread"></div> 
</body> 
</html>""" 

tree = lxml.html.fromstring(html) 

elements = tree.find_class("bread") 

for element in elements: 
    print lxml.html.tostring(element) 

Da:

<div class="bread butter"></div> 
<div class="bread"></div> 
+0

+1 Aunque esto no ayuda a @allie a escribir el código BeautifulSoup, lxml es muy superior. – Henry

+0

Aunque aprecio la elegancia de eso, BeautifulSoup es lo que ya está aquí, y por el momento, eso es lo que necesito usar. :) –

Cuestiones relacionadas