BS4 replace_with для замены новым тегом

#python #beautifulsoup #replacewith

#python #beautifulsoup #замените с

Вопрос:

Мне нужно найти определенные слова в html-файле и заменить их ссылками. Результатом должно быть то, что файл (отображаемый браузером) позволяет вам переходить по ссылкам как обычно. Beautiful Soup автоматически экранирует тег. Как я могу избежать такого поведения?

Минимальный пример

 #!/usr/bin/env python3
from bs4 import BeautifulSoup
import re

html = 
'''
   Identify
'''
soup = BeautifulSoup(html,features="html.parser")
for txt in soup.findAll(text=True):
  if re.search('identi',txt,re.I) and txt.parent.name != 'a':
    newtext = re.sub('identify', '<a href="test.html"> test </a>', txt.lower())
    txt.replace_with(newtext)
print(soup)
  

Результат:

 amp;<a href="test.html"amp;> test amp;</aamp;>
  

Предполагаемый результат:

 <a href="test.html"> test </a>
  

Ответ №1:

Вы можете поместить новый soup с разметкой в качестве параметра в .replace_with() , например:

 import re
from bs4 import BeautifulSoup


html = '''
   Other Identify Other
'''
soup = BeautifulSoup(html,features="html.parser")
for txt in soup.findAll(text=True):
  if re.search('identi',txt,re.I) and txt.parent.name != 'a':
    new_txt = re.sub(r'identi[^s]*', '<a href="test.html">test</a>', txt, flags=re.I)
    txt.replace_with(BeautifulSoup(new_txt, 'html.parser'))

print(soup)
  

С принтами:

    Other <a href="test.html">test</a> Other
  

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

1. Спасибо! Это сработало как по волшебству. У меня на уме было это решение на ранней стадии, но затем я отказался от него, столкнувшись с другой проблемой.

Ответ №2:

Вы можете использовать w3lib , это replace_entities() функция для замены HTML-объектов из строки.

Для установки: pip install w3lib

 from bs4 import BeautifulSoup
import re
from w3lib.html import replace_entities
html = 
'''
   Identify
'''
soup = BeautifulSoup(html,features="html.parser")
for txt in soup.findAll(text=True):
  if re.search('identi',txt,re.I) and txt.parent.name != 'a':
    newtext = re.sub('identify', r'<a href="test.html"> test </a>', txt.lower())
    txt.replace_with(newtext)

print(replace_entities(str(soup))) #str(soup) as its BeautifulSoup type not str

#Output
>>> <a href="test.html"> test </a>
  

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

1. Большое вам спасибо! Хотя ваше решение, вероятно, работает также, решение Андрея не нуждается в дополнительном импорте, поэтому я предпочел его ответ.