Разделите плоский HTML — документ на разделы по тегам- Beautifulsoup

#python #web-scraping #beautifulsoup

Вопрос:

У меня есть плоский HTML-документ, в котором различные элементы разделены тегами H2:

 <h2>section 1</h2>
other elements in the section...
<h2>section 2</h2>
other elements in the section...
 

Мне нужно разделить документ на иерархические разделы с помощью BS4.. в основном это то, что я с нетерпением жду:

 <section>
  <h2>Section 1</h2>
  elements following the previous H2
</section>

<section>
  <h2>Section 2</h2>
  elements following the previous H2 
</section>
 

Как это сделать с помощью селекторов BS4/XPATH или CSS?

Мне нужно получить элементы между двумя тегами H2 с помощью BS4…

конечно, я могу линейно пересечь дерево DOM (текущий документ на самом деле больше похож на плоский массив) и разделить его на части, но это было бы некрасиво…

Комментарии:

1. Итак, вам нужен простой текстовый файл в качестве выходного документа?

2. @MartinEvans на самом деле нет, я могу выполнить преобразование позже… в основном я ищу, чтобы сгруппировать плоский массив HTML-элементов в разделы (обозначенные заголовком H2)… Я могу линейно сканировать весь DOM и разбивать элементы на куски.. но мне было интересно, есть ли более простой способ сделать это с помощью beautifulsoup

Ответ №1:

BeautifulSoup позволяет вставлять теги, поэтому вы можете добавлять <section> теги вокруг <h2>text элементов следующим образом:

 from bs4 import BeautifulSoup
from copy import copy

html = """<html><body>
<h2>section 1</h2>
other elements in the section...
<h2>section 2</h2>
other elements in the section...    
</body></html>"""

soup = BeautifulSoup(html, "html.parser")

for h2 in soup.find_all('h2'):
    section_soup = soup.new_tag('section')
    section_soup.append(copy(h2))
    section_soup.append(h2.next_sibling)
    h2.insert_before(section_soup)
    h2.extract()
    
print(soup)
 

Предоставление вам обновленного HTML-кода в виде:

 <html><body>
<section><h2>section 1</h2>
other elements in the section...
</section><section><h2>section 2</h2>
other elements in the section...    
</section></body></html>
 

Это работает, сначала создавая новый тег раздела и добавляя <h2> в него копию тега, а затем следующий за ним текст. Затем он вставляет этот новый суп перед существующим <h2> тегом. Наконец, он удаляет исходный <h2> тег.