Regex для удаления условных комментариев - PullRequest
5 голосов
/ 25 сентября 2008

Мне нужно регулярное выражение, которое может соответствовать условным комментариям на исходной странице HTML, поэтому я могу удалить только те. Я хочу сохранить регулярные комментарии.

Я также хотел бы избежать использования. *? обозначение, если это возможно.

Текст

foo

<!--[if IE]>

<style type="text/css">

ul.menu ul li{
    font-size: 10px;
    font-weight:normal;
    padding-top:0px;
}

</style>

<![endif]-->

bar

и я хочу удалить все в <!--[if IE]> и <![endif]-->

РЕДАКТИРОВАТЬ: Именно из-за BeautifulSoup я хочу удалить эти теги. BeautifulSoup не может разобрать и дает неполный источник

EDIT2: [если IE] не единственное условие. Их намного больше, и у меня нет списка всех возможных комбинаций.

EDIT3: Решение Винко Врсаловича работает, но настоящая проблема, почему Beautifulsoup не удалось, была из-за мошеннического комментария в условном комментарии. Как

<!--[if lt IE 7.]>
<script defer type="text/javascript" src="pngfix_253168.js"></script><!--png fix for IE-->
<![endif]-->

Обратите внимание на комментарий <!--png fix for IE-->?

Хотя моя проблема была решена, я бы хотел получить решение для регулярных выражений для этого.

Ответы [ 7 ]

5 голосов
/ 25 сентября 2008
>>> from BeautifulSoup import BeautifulSoup, Comment
>>> html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
>>> soup = BeautifulSoup(html)
>>> comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
>>> [comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
>>> print soup.prettify()
<html>
</html>
>>>     

Python 3 с bf4:

from bs4 import BeautifulSoup, Comment
html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
soup = BeautifulSoup(html, "html.parser")
comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
[comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
print (soup.prettify())

Если ваши данные запутались в BeautifulSoup, вы можете исправить их перед рукой или настроить анализатор среди других решений.

РЕДАКТИРОВАТЬ: В соответствии с вашим комментарием, вы просто изменяете лямбда, переданную, чтобы найти все, что вам нужно (я изменил его)

2 голосов
/ 26 сентября 2008

На мой взгляд, вам нужно беспокоиться только о скрытых внизу комментариях (начинающихся с <!--), и вам не нужно сопоставлять что-либо кроме слова if и пространство после него. Это должно делать то, что вы хотите:

"<!--\[if\s(?:[^<]+|<(?!!\[endif\]-->))*<!\[endif\]-->"

Этот беспорядок в середине - чтобы удовлетворить ваше желание не использовать .*?, но я не думаю, что оно того стоит. Подход .*? должен работать нормально, если вы скомпилируете регулярное выражение с установленным флагом Re.S или поместите его в (?s:...). Например:

"(?s:<!--\[if\s.*?<!\[endif\]-->)"
2 голосов
/ 25 сентября 2008

Вот что вам нужно:

<!(|--)\[[^\]]+\]>.+?<!\[endif\](|--)>

Это отфильтрует все виды условных комментариев, включая:

<!--[if anything]>
    ...
<[endif]-->

и

<![if ! IE 6]>
    ...
<![endif]>

EDIT3 : решение Винко Врсаловича работает, но настоящая проблема, почему не удалось выполнить Beautifulsoup, заключалась в мошенническом комментарии в условном комментарии. Как

Заметили комментарий?

Несмотря на то, что моя проблема была решена, я бы хотел получить решение для регулярных выражений для этого.

Как насчет этого:

(<!(|--)\[[^\]]+\]>.*?)(<!--.+?-->)(.*?<!\[endif\](|--)>)

Сделайте замену для этого регулярного выражения, оставив \ 1 \ 4 (или $ 1 $ 4) в качестве замены.
Я знаю, что это так. *? и. +? см. мой комментарий к этому сообщению.

1 голос
/ 26 сентября 2008

Я бы просто пошел с:

import re

html = """fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs---><!--[if lt IE 7.]>\
<script defer type="text/javascript" src="pngfix_253168.js"></script><!--png fix for IE-->\
<![endif]-->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->"""

# here the black magic occurs (whithout '.')
clean_html = ''.join(re.split(r'<!--\[[^¤]+?endif]-->', html))

print clean_html

'fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->'

N.B: [^ ¤] будет соответствовать любому символу, который не является '¤'. Это действительно полезно, так как это молниеносно, и этот символ можно найти на любой клавиатуре. Но хитрость в том, что ее действительно сложно набрать (никто не напишет ее по ошибке), и никто ею не пользуется: это обычный символ для разработки денег.

Если вы не хотите использовать ¤, вы можете использовать chr (7) для генерации символа "системный звонок", который не может быть напечатан и не найден на веб-странице; -)

1 голос
/ 25 сентября 2008

@ Бенуа

Малая коррекция (с включенной мультилинией):

 "<!--\[if IE\]>.*?<!\[endif\]-->"
0 голосов
/ 25 сентября 2008

Это работает в Visual Studio 2005, где нет опции перевода строки:

\<!--\[if IE\]\>{.|\n}*\<!\[endif\]--\>

0 голосов
/ 25 сентября 2008

Не используйте регулярное выражение для этого. Вы запутаетесь в комментариях, содержащих открывающие теги, а что нет, и поступите неправильно. HTML не является регулярным, и попытка изменить его одним регулярным выражением не удастся.

Используйте для этого HTML-парсер. BeautifulSoup - хороший, простой, гибкий и надежный инструмент, способный работать с реальным (то есть безнадежно нарушенным) HTML. С его помощью вы можете просто просмотреть все узлы комментариев, изучить их содержимое (вы можете использовать регулярное выражение для , что , если хотите) и удалить их, если их нужно удалить.

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