python — файлы BeautifulSoup и php / html

Я использую BeautifulSoup для преобразования относительных URL-адресов в некоторых древних HTML-файлах с архивного сайта в абсолютные URL-адреса (в основном, чтобы их можно было лучше таргетировать по правилам .htaccess). У меня есть эта часть: поиск определенных тегов и их атрибутов, используйте urllib.parse.urljoin (это Python3) для исправления. Хорошо.

Тем не менее, есть и некоторые .php файлы в этой коллекции, начиная с более поздних лет существования этого сайта. В основном они используют 3-5 строк для включения других файлов .php, тогда как остальные — HTML, хотя есть некоторые исключения.

Проблема: Парсеры BeautifulSoup пытаются интерпретировать, что между <?php ?> теги. На самом деле, бывают случаи, когда они просто выбрасывают только угловые скобки, но оставляют вопросительные знаки — поведение, на которое я хакерски обращался так:

for c in soup.contents:
c = str(c) # previously a BeautifulSoup Tag

# I don't need soup after this point, hence not reconstructing contents
c = ('<' if c.startswith('?') else '') + c
c = c + ('>' if c.endswith('?') else '')

Но в любом случае я заметил, что в целом <?php ?> теги часто искажались, по-разному, в зависимости от парсера. Например, парсер html5lib принимает следующие строки:

<?
//echo "BEGIN PAGE: " . $_SESSION["i"]."<br>";
include ('util.php');

И интерпретирует тег как заканчивающийся на > что закрывается <br>,

Я бы предпочел, чтобы теги php оставались в покое. (Очевидно, что в идеальном мире парсер будет читать их и работать с любым внутренним HTML, но это похоже на слишком много!)

Возможные решения

  1. Пропускайте файлы .php и работайте только с .html — выполняемая работа не обязательна, это просто оптимизация, поэтому больших потерь не будет;
  2. Найдите парсер BeautifulSoup, не упомянутый в документации, который лучше обрабатывает эти случаи;
  3. Сам разбирай текст, извлекай все <?php ?> блокировать и повторно вставлять после завершения работы с BeautifulSoup, стараясь вспомнить, где они должны упасть (что может быть очень сложно, если любой из этих тысяч файлов имеет <?php echo 'foobar' ?> в середине строки HTML, например)
  4. Как и выше, программно защищать все <?php ?> теги от парсера, например вставляя вокруг них HTML-комментарии, а затем убирайте защиту после супа

3

Решение

Чтобы ответить на мой собственный вопрос … 🙂

Я использовал решение № 4: программно защитить все <?php ?> теги из парсера, вставляя вокруг них HTML-комментарии. Затем парсер пропускает интерпретацию того, что находится внутри комментария. Позже, при использовании soup.prettify() или же soup.contents, вывод можно просто дать прямую замену <!--<? с <? и аналогично для закрытия тегов.

Обратите внимание, что это не работает для тегов PHP, используемых для генерации динамического содержимого внутри определенных тегов HTML, например:

<a href= "<? echo foo_bar(); ?>" >

Текущие версии html.parser, lxml, а также html5lib все интерпретируют это как серию бессмысленных атрибутов <a>даже когда теги PHP заключены в комментарии HTML. В таких случаях я вручную извлекал теги с помощью регулярных выражений, чтобы решить мою проблему.

1

Другие решения

Других решений пока нет …