BeautifulSoup и поиск по классу
Возможный дубликат:
Beautiful Soup не может найти класс CSS, если у объекта есть и другие классы
Я использую BeautifulSoup для поиска tables
в HTML. Проблема, с которой я сейчас сталкиваюсь, заключается в использовании пробелов в атрибуте class
. Если мой HTML читает <html><table class="wikitable sortable">blah</table></html>
, я не могу извлечь его из следующего (где я должен был бы найти tables
как с wikipedia
, так и wikipedia sortable
для class
):
BeautifulSoup(html).findAll(attrs={'class':re.compile("wikitable( sortable)?")})
Это найдет таблицу, если мой HTML только <html><table class="wikitable">blah</table></html>
. Аналогично, я попытался использовать "wikitable sortable"
в своем регулярном выражении, и это тоже не будет соответствовать. Любые идеи?
Ответы
Ответ 1
Совпадение шаблона также завершится неудачно, если wikitable
появится после другого класса CSS, как в class="something wikitable other"
, поэтому, если вы хотите, чтобы все таблицы, атрибут класса которых содержит класс wikitable
, вам нужен шаблон, который принимает больше возможностей:
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
Результат:
<table class="sortable wikitable other">blah</table>
<table class="wikitable sortable">blah</table>
<table class="wikitable"><blah></blah></table>
Только для записи я не использую BeautifulSoup и предпочитаю использовать lxml, как упомянули другие.
Ответ 2
Одна из вещей, которая делает lxml лучше, чем BeautifulSoup, - это поддержка правильного выбора класса CSS (или даже поддерживает полные селектора css, если вы хотите их использовать)
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)
дает:
<div class="bread butter"></div>
<div class="bread"></div>