Как запретить BeautifulSoup4 добавлять дополнительные теги <html> <body> в суп?

В версиях BeautifulSoup до 3 я мог легко взять любой фрагмент HTML и получить строковое представление следующим образом:

from BeautifulSoup import BeautifulSoup soup3 = BeautifulSoup('<div><b>soup 3</b></div>') print unicode(soup3) '<div><b>soup</b></div>' 

Однако с помощью BeautifulSoup4 такая же операция создает дополнительные теги:

 from bs4 import BeautifulSoup soup4 = BeautifulSoup('<div><b>soup 4</b></div>') print unicode(soup4) '<html><body><div><b>soup 4</b></div></body></html>' ^^^^^^^^^^^^ ^^^^^^^^^^^^^^ 

Мне не нужны внешние теги <html><body>..</body></html> которые добавляет BS4. Я просмотрел документы BS4, а также искал внутри класса, но не смог найти никаких параметров для подавления дополнительных тегов в результатах. Как мне это сделать? Переход на v3 не является опцией, поскольку синтаксический анализатор SGML, используемый в BS3, не так хорош, как lxml или html5lib , доступные с BS4.

Если вы хотите, чтобы ваш код работал на компьютере каждого пользователя, независимо от того, какой он был установлен и т. Д. ( lxml же версия lxml построенная на libxml2 2.9 по сравнению с 2.8, действует совсем по-другому, stdlib html.parser имел некоторые радикальные изменения между 2.7.2 и 2.7.3, …), вы в значительной степени должны обрабатывать все законные результаты.

Если вы знаете, что у вас есть фрагмент, что-то вроде этого даст вам именно этот фрагмент:

 soup4 = BeautifulSoup('<div><b>soup 4</b></div>') if soup4.body: return soup4.body.next elif soup4.html: return soup4.html.next else: return soup4 

Конечно, если вы знаете, что ваш фрагмент – это один div , это еще проще – но не так-то просто подумать о прецеденте, где вы бы это знали:

 soup4 = BeautifulSoup('<div><b>soup 4</b></div>') return soup4.div 

Если вы хотите знать, почему это происходит:

BeautifulSoup предназначен для анализа HTML-документов. HTML-фрагмент не является допустимым документом. Это довольно близко к документу, но это недостаточно эффективно, чтобы гарантировать, что вы вернетесь именно к тому, что вы ему дадите.

Как Различия между парсерами говорят:

Существуют также различия между парсерами HTML. Если вы дадите Beautiful Soup идеальный HTML-документ, эти различия не будут иметь значения. Один парсер будет быстрее другого, но все они дадут вам структуру данных, которая будет выглядеть точно так же, как исходный HTML-документ.

Но если документ не идеально сформирован, разные парсеры будут давать разные результаты.

Итак, хотя эта точная разница не документирована, это всего лишь частный случай того, что есть.

Как было отмечено в старой документации BeautifulStoneSoup :

Класс BeautifulSoup полон эвристик, основанных на веб-браузере, для того, чтобы предсказать намерение авторов HTML. Но у XML нет фиксированного набора тегов, поэтому эти эвристики не применяются. Так что BeautifulSoup не очень хорошо разбирается в XML.

Используйте класс BeautifulStoneSoup для анализа XML-документов. Это общий класс, не имеющий специальных знаний о любом диалекте XML и очень простых правилах о вложенности тегов …

И в документах BeautifulSoup4 :

Для обработки XML-данных уже нет класса BeautifulStoneSoup. Для анализа XML вы передаете «xml» в качестве второго аргумента конструктору BeautifulSoup. По той же причине конструктор BeautifulSoup больше не распознает аргумент isHTML.

Возможно, это даст то, что вы хотите.