2025, Nov 08 09:04
Разбор полусформатированного текста для WordPress с помощью регулярных выражений
Извлекайте H-заголовки и блоки Markdown из полусформатированного текста с помощью регулярных выражений. Шаблоны и советы для публикации в WordPress API.
Разобрать полусформатированный текст до состояния, пригодного для публикации через WordPress API, значит надежно извлечь структуру. Если в исходнике заголовки и абзацы размечены простыми маркерами, аккуратно составленное регулярное выражение обычно хватает, чтобы разбить текст на заголовки и соответствующие им блоки.
Пример входных данных и первая попытка
Рассмотрим источник, где перемешаны маркеры заголовков и абзацы примерно так:
'**H1: Some text**\n\nSome text as paragraph.\n\n**H2: A subheader**\n\nText from the subheader.\n\nA line break with some more text.\n\n**H2: Another sub hearder**\n\n**H3: A sub sub headerНаивная попытка может начаться с шаблонов, которые «ловят» конкретный заголовок и пытаются захватить ближайший текст:
import re
payload = myFullText
h1_hits = re.findall('H1.*?ph\.', payload)
payload = myFullText
h1_hits = re.findall('H1.*?\n\n\.', payload)Оба вызова могут вернуть пустой результат — это верный признак, что шаблон не соответствует реальным маркерам и структуре строк в тексте.
Что здесь на самом деле важно
Регулярные выражения подходят для такой задачи, но только когда они опираются на реальную структуру. В примере выше заголовки отмечены как полужирные фрагменты с уровнем и названием, например **H2: A subheader**. Пытаться захватывать произвольный диапазон от H1 до расплывчатого окончания вроде ph. или полагаться на конкретное сочетание переводов строк — путь в никуда: такой подход плохо обобщается и часто промахивается. Ключ — нацелить шаблон на сами маркеры заголовков. Когда содержимое может занимать несколько строк до следующего заголовка или конца текста, нужен шаблон, который останавливается у границы следующего заголовка, а не угадывает конец абзаца.
Как ловить полужирные заголовки уровня H
Если заголовки оформлены полужирными маркерами вроде **H1: Title**, извлекайте уровень и название напрямую:
import re
source_blob = myFullText
hdr_expr = r"\*\*(H\d): (.*?)\*\*"
found_headers = re.findall(hdr_expr, source_blob)Такой шаблон достает токен уровня, например H1, вместе с заголовком между звездочками. Это точный способ собрать все заголовки, прежде чем сопоставлять их с последующим содержимым.
Извлечение заголовков в стиле Markdown вместе с их абзацами
Если в тексте используются маркеры в стиле Markdown (#), можно за один проход захватывать и заголовки, и идущий за ними блок. Следующий шаблон собирает маркер заголовка, его текст и все до следующего заголовка или конца строки:
import re
text_data = """
# Header 1
This is the first paragraph under header 1.
## Header 2
This is some text under header 2.
Another paragraph under the same header.
### Header 3
More content here.
"""
block_pat = r"^(#{1,6})\s+(.*?)\n(.*?)(?=\n#{1,6}\s+|\Z)"
chunks = re.findall(block_pat, text_data, re.DOTALL | re.MULTILINE)
for level_marks, heading, block in chunks:
depth = len(level_marks)
section_body = block.strip()
print(f"H{depth}: {heading}")
print(f"Paragraph:\n{section_body}")Этот прием извлекает уровень заголовка как количество символов #, сам текст заголовка и прилегающий снизу блок — удобно, когда важно сохранить абзацы вместе с их заголовком.
Чтобы получить только строки заголовков и убрать символы #, сопоставьте строку заголовка и вычислите уровень по длине маркера:
import re
md_text = text_data
line_pat = r"^(#{1,6})\s+(.*)$"
header_lines = re.findall(line_pat, md_text, re.MULTILINE)
for marks, title_text in header_lines:
print(f"H{len(marks)}: {title_text}")Почему это важно при публикации в WordPress
WordPress рассчитывает на корректную структуру. Независимо от того, превращаете ли вы найденные фрагменты в HTML‑заголовки и абзацы или раскладываете их по полям для API‑запроса, точное извлечение уровня заголовка и связанного текста предотвращает «кривые» публикации и помогает не потерять блоки при импорте.
Итоги и практические советы
Используйте re.findall с шаблонами, отражающими реальные маркеры. Для полужирных H‑заголовков точно совпадайте с фрагментами вида **Hn: Title**. Для Markdown‑входа опирайтесь на заякоренное многострочное выражение с границей до следующего заголовка и вычисляйте уровень по количеству символов #. Имея такую структуру, привести результат к формату, ожидаемому WordPress API, — уже вопрос простой верстки.
Статья основана на вопросе на StackOverflow от hacking_mike и ответе от Arpan Gautam.