Оставьте один вложенный div в HTML do c и очистите все остальные - PullRequest
1 голос
/ 12 июля 2020

Я пытаюсь убрать хлам из зашумленного, глубоко вложенного HTML документа. Я хотел бы сохранить структуру страницы, просто очистите содержимое окружающих div s.

Структура выглядит примерно так:

<div class="a">
    ...stuff...
  <div>
   ...stuff....
    <div class="my_class_of_interest">
      ....several levels deeper...
      </div>
    ..stuff..
  </div>
  ...stuff..
</div>

Я бы хотел чтобы стереть все, что находится за пределами div, я хочу, но оставьте все внутри этого div. Это код, который я пробовал:

for div in soup.find_all("div"):
    if div.has_attr('class'):
        if div['class'] == "my_class_of_interest":
            continue
    div.clear()

Но это стирает мои div интереса, я подозреваю, потому что я очищаю его родительский элемент, и очистка идет полностью вниз. Есть ли способ очистить текст div, не стирая вложенные div s? Или есть способ лучше?

Ответы [ 2 ]

2 голосов
/ 12 июля 2020

Надеюсь, я хорошо понял ваш вопрос. Этот скрипт сотрет все строки, окружающие интересующий тег:

from bs4 import BeautifulSoup, Tag


txt = '''
<div class="a">
  ...stuff...
  <div>
    ...stuff....
    <div class="my_class_of_interest">
      ....several levels deeper...
    </div>
  ..stuff..
  </div>
  ...stuff..
</div>'''

soup = BeautifulSoup(txt, 'html.parser')

# print soup before clearing
print(soup)

def clear(tag):
    for c in tag.contents:
        if isinstance(c, Tag) and c.name == 'div' and 'my_class_of_interest' in c.get('class', []):
            continue
        elif isinstance(c, Tag):
            clear(c)
        else:
            c.replace_with('')

clear(soup.select_one('div.a'))

print('-' * 80)

# print soup after clearing:
print(soup.prettify())

Выводит:

<div class="a">
  ...stuff...
  <div>
    ...stuff....
    <div class="my_class_of_interest">
      ....several levels deeper...
    </div>
  ..stuff..
  </div>
  ...stuff..
</div>
--------------------------------------------------------------------------------
<div class="a">
 <div>
  <div class="my_class_of_interest">
   ....several levels deeper...
  </div>
 </div>
</div>
1 голос
/ 12 июля 2020

Другой вариант, используя l xml:

import lxml.html as lh
interest = """your html above"""
doc = lh.fromstring(interest)
retain = ''
for d in doc.xpath('//*'):
    if d.attrib and d.attrib.values()[0]=="my_class_of_interest":
           retain += d.text
    d.text =""
    d.tail=""
for target in doc.xpath('//div[@class="my_class_of_interest"]'):
    target.text=retain
print(lh.tostring(doc).decode())

Вывод:

<div class="a"><div><div class="my_class_of_interest">
      ....several levels deeper...
      </div></div></div>
...