Проблема с доступом к атрибутам в BeautifulSoup - PullRequest
6 голосов
/ 01 мая 2011

У меня проблемы с использованием Python (2.7). Код в основном состоит из:

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'

Я ожидал, что первый оператор if будет работать правильно (то есть: если at не существует, выведите "nothing"), но он всегда ничего не печатает (т.е. всегда False). Второй if, с другой стороны, всегда равен True, что приведет к повышению значения KeyError при попытке доступа к at из второго элемента <el>, который, конечно, не существует.

Ответы [ 4 ]

7 голосов
/ 01 мая 2011

Оператор in предназначен для типов последовательности и отображения, что заставляет вас думать, что объект, возвращаемый BeautifulSoup, должен правильно его реализовывать?Согласно документации BeautifulSoup, вы должны обращаться к атрибутам, используя синтаксис [].

Re hasattr, я думаю, вы перепутали атрибуты HTML / XML и атрибуты объектов Python.hasattr для последнего, и BeaitufulSoup AFAIK не отражает атрибуты HTML / XML, которые он анализировал, в своих собственных атрибутах объекта.

PS обратите внимание, что объект Tag в BeautifulSoup реализует __contains__ - так что, возможно, вы пытаетесь использовать не тот объект?Можете ли вы показать полный, но минимальный пример, который демонстрирует проблему?


Запуск этого:

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']

Я получаю:

<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'

Что яожидается.У первого el есть атрибут at, у второго нет - и это выдает KeyError.


Обновление 2: BeautifulSoup.Tag.__contains__ просматривает содержимое тега, а не его атрибуты.Чтобы проверить, существует ли атрибут, используйте in.

1 голос
/ 02 мая 2011

Чтобы просто выполнить поиск элемента по имени тега, решение для анализа может быть более читабельным (и без использования устаревших API, таких как 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

Для дополнительного уточнения функция Pyparsing позволяетопределите фильтрующее действие синтаксического анализа, чтобы теги совпадали только в том случае, если найдено определенное значение атрибута (или атрибута-любое значение):

# 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
1 голос
/ 01 мая 2011

Если ваш код так прост, как вы его предоставили, вы можете решить его компактно:

for x in z.findAll('el'):
    print x.get('at', 'nothing')
0 голосов
/ 01 мая 2011

Я обычно использую метод get () для доступа к атрибуту

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

if name:
    print 'anchor'
if href:
    print 'link'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...