Я просто не могу понять это правильно. BeautifulSoup4 настолько сбивает с толку.
Я пытаюсь исправить неопубликованные ссылки Markdown в HTML тексте. Регулярное выражение:
REF = re.compile(r"\[(?P<title>.+?)\]\[(?P<identifier>.*?)\]")
Поскольку, очевидно, BS4 использует match
с регулярными выражениями, я расширил регулярное выражение с помощью
REF = re.compile(r".*\[(?P<title>.+?)\]\[(?P<identifier>.*?)\].*", re.DOTALL)
Цель - найти такие строки и заменить их на фактические ссылки <a>
, но не в том случае, если они находятся в теге <code>
(независимо от глубины). У меня есть сопоставление для получения URL-адреса из identifier
.
[<code>title<code>][identifier]
должно быть сопоставлено, но <code>[title][identifier]
не должно.
Если ввод:
<p>[<code>title<code>][identifier]</p>
Вывод должен быть:
<p><a id="identifier" href="http://example.com"><code>title<code></a></p>
Однако следующий ввод должен остаться без изменений:
<p><code>[title][identifier]</code></p>
Я пробовал следующее:
tags = [tag.parent for tag in soup.find_all(text=REF) if not tag.find_parent("code")]
... но отсутствовали теги. Я нашел объяснение в этом посте: BeautifulSoup - поиск по тексту внутри тега . Кажется, text
(или новое имя string
, хотя я обнаружил, что поведение отличается) вернет None
, когда в теге есть другие теги, то есть тег <p>[<code>title<code>][identifier]</p>
не будет совпадать.
Я также думал, что пост дал решение:
tags = list(
soup.find_all(
lambda tag: tag.name != "code" and
not tag.find_parent("code") and
REF.search(tag.text)
)
)
... но теперь вместо того, чтобы давать мне метки рядом с листьями, он возвращает root метки, такие как <html>
и <body>
, потому что tag.text
возвращает полный, рекурсивный текст всех потомков . Тогда, конечно, эти теги содержат текст, соответствующий регулярному выражению, но внутри <code>
тегов .
Я думаю, что лучшим решением было бы попробовать регулярное выражение для текста тега, ограниченного определенная глубина. Если текст глубины 1 <p>[<code>title
] [идентификатор]
равен
[ ][identifier]
, а текст глубины 2 того же тега равен
[<code>title
] [идентификатор] , то глубина 2 все Мне нужно.
Есть ли способ сделать это? Или у вас есть другое решение? Я подумал, что, возможно, смогу перебрать все теги от листьев до root, в ширину, но у меня все еще будет та же проблема с tag.text
, возвращающим также текст всех потомков.