Простой .html фильтр в python - изменяйте только текстовые элементы - PullRequest
0 голосов
/ 07 мая 2019

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

Один хороший пример -измените <p><div class="speech">it's hard to find his "good" side! He has <i>none</i>!<div></p> на <p><div class="speech">it's hard to find his &ldquo;good&rdquo; side! He has <i>none</i>!<div></p>.

Я могу легко проанализировать свои файлы с помощью html.parser, но неясно, как сгенерировать файл результатов, который должен быть максимально похож на ввод (без переформатирования).

Я посмотрел на Beautiful-Soup, но он действительно кажется слишком большим для этой (предположительно?) Простой задачи.

Примечание: я не нуждаюсь / хочуобслуживать файлы .html в любом браузере;Мне просто нужно, чтобы они были обновлены (возможно на месте) с (слегка) измененным содержимым.

ОБНОВЛЕНИЕ:

Следуя совету @soundstripe, я написал следующий код:

import bs4
from re import sub

def handle_html(html):
    sp = bs4.BeautifulSoup(html, features='html.parser')
    for e in list(sp.strings):
        s = sub(r'"([^"]+)"', r'&ldquo;\1&rdquo;', e)
        if s != e:
            e.replace_with(s)
    return str(sp).encode()

raw = b"""<p><div class="speech">it's hard to "find" his "good" side! He has <i>none</i>!<div></p>"""
new = handle_html(raw)
print(raw)
print(new)

К сожалению, BeautifulSoup пытается быть слишком умным из своего (и моего) собственного блага:

b'<p><div class="speech">it\'s hard to "find" his "good" side! He has <i>none</i>!<div></p>'
b'<p><div class="speech">it\'s hard to &amp;ldquo;find&amp;rdquo; his &amp;ldquo;good&amp;rdquo; side! He has <i>none</i>!<div></div></div></p>'

, то есть: он преобразует простой & в &amp;, тем самым нарушая сущность &ldquo; (обратите внимание, что я работаю сbytearrays, а не strings. Это актуально?).

Как это исправить?

1 Ответ

1 голос
/ 07 мая 2019

Я не знаю, почему бы вам не использовать BeautifulSoup. Вот пример, который заменяет ваши кавычки, как вы спрашиваете.

import re
import bs4

raw = b"""<p><div class="speech">it's hard to find his "good" side! He has <i>none</i>!<div></p> to <p><div class="speech">it's hard to find his &ldquo;good&rdquo; side! He has <i>none</i>!<div></p>"""
soup = bs4.BeautifulSoup(raw, features='html.parser')

def replace_quotes(s):
    return re.sub(r'"([^"]+)"', r'&ldquo;\1&rdquo;', e)


for e in list(soup.strings):
    # wrapping the new string in BeautifulSoup() call to correctly parse entities
    new_string = bs4.BeautifulSoup(replace_quotes(e))
    e.replace_with(new_string)

# use the soup.encode() formatter keyword to specify you want html entities in your output
new = soup.encode(formatter='html')


print(raw)
print(new)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...