2011-05-01 12 views
6

Tengo problemas al usar Python (2.7). El código consta básicamente de:Problema al acceder a los atributos en BeautifulSoup

str = '<el at="some">ABC</el><el>DEF</el>' 
z = BeautifulStoneSoup(str) 

for x in z.findAll('el'): 
    # if 'at' in x: 
    # if hasattr(x, 'at'): 
     print x['at'] 
    else: 
     print 'nothing' 

que espera que la primera declaración if funcione correctamente (es decir: si at no existe, imprimir "nothing"), pero siempre se imprime nada (es decir: siempre es False). Por otro lado, el segundo if siempre es True, lo que hará que el código muestre un KeyError al intentar acceder al at desde el segundo elemento <el>, que por supuesto no existe.

+1

'str' no es su La mejor opción para un nombre varible, ya que enmascara el tipo de cadena integrada. ¿Qué tal algo como 'xmltext'? – PaulMcG

Respuesta

7

El operador in es para tipos de secuencia y mapeo, ¿qué le hace pensar que el objeto devuelto por BeautifulSoup se supone que debe implementarlo correctamente? De acuerdo con los documentos de BeautifulSoup, debe acceder a los atributos utilizando la sintaxis [].

Re hasattr, creo que confundió atributos HTML/XML y atributos de objeto Python. hasattr es para este último y BeaitufulSoup AFAIK no refleja los atributos HTML/XML que analizó en sus propios atributos de objeto.

P.S. tenga en cuenta que el objeto Tag en BeautifulSouphace implementar __contains__ - ¿entonces quizás esté intentando con el objeto equivocado? ¿Puedes mostrar un ejemplo completo pero mínimo que demuestre el problema?


La ejecución de este:

from BeautifulSoup import BeautifulSoup 

str = '<el at="some">ABC</el><el>DEF</el>' 
z = BeautifulSoup(str) 

for x in z.findAll('el'): 
    print type(x) 
    print x['at'] 

me sale:

<class 'BeautifulSoup.Tag'> 
some 
<class 'BeautifulSoup.Tag'> 
Traceback (most recent call last): 
    File "soup4.py", line 8, in <module> 
    print x['at'] 
    File "C:\Python26\lib\site-packages\BeautifulSoup.py", line 601, in __getitem__ 
    return self._getAttrMap()[key] 
KeyError: 'at' 

que es lo que esperaba. El primer el tiene un atributo at, el segundo no - y esto arroja un KeyError.


Actualización 2: BeautifulSoup.Tag.__contains__ la mira dentro de los contenidos de la etiqueta, no sus atributos. Para verificar si existe un atributo, use in.

+0

'in' también es parte de la interfaz de mapeo y se refiere a la clave en esos casos. – delnan

+0

@delnan: gracias, agregué esta aclaración a la respuesta –

+0

El problema con eso es acceder a un elemento que no existe levantará un 'KeyError'. – NullUserException

0

que suelen utilizar el método get() para acceder atributo

link = soup.find('a') 
href = link.get('href') 
name = link.get('name') 

if name: 
    print 'anchor' 
if href: 
    print 'link' 
1

Si el código es tan simple como que ya ha proporcionado, se puede resolver de una manera compacta con:

for x in z.findAll('el'): 
    print x.get('at', 'nothing') 
1

Para simplemente busque un elemento por nombre de etiqueta, una solución de pyparsing podría ser más legible (y sin utilizar API desaprobadas como has_key):

from pyparsing import makeXMLTags 

# makeXMLTags creates a pyparsing expression that matches tags with 
# variations in whitespace, attributes, etc. 
el,elEnd = makeXMLTags('el') 

# scan the input text and work with elTags 
for elTag, tagstart, tagend in el.scanString(xmltext): 
    if elTag.at: 
     print elTag.at 

Para un refinamiento adicional, pyparsing le permite definir una acción de filtrado de análisis de manera que las etiquetas sólo igualará si un atributo de valor particular (o atributo-AnyValue) se encuentra:

# import parse action that will filter by attribute 
from pyparsing import withAttribute 

# only match el tags having the 'at' attribute, with any value 
el.setParseAction(withAttribute(at=withAttribute.ANY_VALUE)) 

# now loop again, but no need to test for presence of 'at' 
# attribute - there will be no match if 'at' is not present 
for elTag, tagstart, tagend in el.scanString(xmltext): 
    print elTag.at 
Cuestiones relacionadas