Есть ли способ получить правильные текстовые поля с помощью XML-парсера Beautiful Soup в документе ниже?
<!DOCTYPE html>
<html>
<body>
<header class="site-header" itemscope itemtype="http://schema.org/WPHeader">
<div>
<p>Lorem ipsum</p>
</div>
</header>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac tempus magna. Morbi maximus enim eu dolor ultricies, quis vestibulum lacus finibus. Maecenas sed fermentum nisi. Sed nec dignissim mi. Curabitur vel magna faucibus, ultrices tortor quis,
gravida metus. Fusce in nisi et ligula feugiat pharetra. Nam sed sapien auctor, egestas sem nec, hendrerit libero. Nulla in semper ligula. Vivamus commodo pulvinar luctus. In ac vehicula felis. In nec bibendum nulla.</p>
</div>
</body>
</html>
Проблема в том, что наличие логического itemscope
заставляет атрибут itemtype
и его значение перемещаться в текстовый узел:
from bs4 import BeautifulSoup
with open('bs4-issue-xml.html', 'r') as f:
html_raw = ''.join(f.read())
soup_lxml = BeautifulSoup(html_raw, 'lxml')
soup_xml = BeautifulSoup(html_raw, 'xml')
assert 'schema.org' not in soup_lxml.header.text
assert 'schema.org' not in soup_xml.header.text # assertion fails
Вот что переносится в header.text
:
In [44]: soup_xml.header.text
Out[44]: 'itemtype="http://schema.org/WPHeader">\n \nLorem ipsum\n\n'
Официальные документы утверждают, что синтаксический анализатор xml
является "единственным в настоящее время поддерживаемым синтаксическим анализатором XML", но он не может обрабатывать обычные логические атрибуты HTML5, если они не находятся в последней позиции, что это то, что я не могу исправить на моей стороне (весь вопрос имеет контекст веб-очистки). Есть ли обходной путь / исправление для случая этого конкретного парсера?
Примечание : ясно, что я знаю, что синтаксический анализатор lxml
(или lxml
сам по себе) в этом случае работает правильно, и меня интересует только использование синтаксического анализатора xml
в Beautiful Суп по другим причинам.