как сделать ширину и высоту х2 используя Python Regular - PullRequest
1 голос
/ 04 мая 2011

Мне нужно проделать много работы, чтобы измениться так:

<img src = "/" height="111" width="10" />

на

<img src = "/" height="222" width="20" />

, поэтому я хочу использовать Python Regular Это мой код:

import re

s = '<img src = "werwerwe" height="111" width="10" />'

def a(x):
    print x.group(2)
    print x.group(4)

ss = re.sub(r'''<img.*(width\s*="?(\d+)"?)*\s*(height\s*="?(\d+)"?)*''',a, s)

print ss

так, что я могу сделать,

спасибо

обновлено:

теперь все в порядке:

import re

s = '<img src = "/" height="111" width="10" />'


def a(x):
    b = x.group(0)
    b = b.replace(x.group(1),str(int(x.group(1))*2))
    b = b.replace(x.group(2),str(int(x.group(2))*2))
    return b

ss = re.sub(r'''<img.*?height=\"(\d+)\".*?width=\"(\d+)\"[^>]*>''',a, s)

print ss

Ответы [ 6 ]

4 голосов
/ 04 мая 2011

Не используйте регулярные выражения для разбора HTML. Используйте BeautifulSoup

>>> from BeautifulSoup import BeautifulSoup
>>> ht = '<html><head><title>foo</title></head><body><p>whatever: <img src="foo/img.png" height="111" width="22" /></p><ul><li><img src="foo/img2.png" height="32" width="44" /></li></ul></body></html>'
>>> soup = BeautifulSoup(ht)
>>> soup
<html><head><title>foo</title></head><body><p>whatever: <img src="foo/img.png" height="111" width="22" /></p><ul><li><img src="foo/img2.png" height="32" width="44" /></li></ul></body></html>
>>> soup.findAll('img')
[<img src="foo/img.png" height="111" width="22" />, <img src="foo/img2.png" height="32" width="44" />]
>>> for img in soup.findAll('img'):
...     ht = int(img['height'])
...     wi = int(img['width'])
...     img['height'] = str(ht * 2)
...     img['width'] = str(wi * 2)
...     
... 
>>> print soup.prettify()
<html>
 <head>
  <title>
   foo
  </title>
 </head>
 <body>
  <p>
   whatever:
   <img src="foo/img.png" height="222" width="44" />
  </p>
  <ul>
   <li>
    <img src="foo/img2.png" height="64" width="88" />
   </li>
  </ul>
 </body>
 </html>
>>> 
2 голосов
/ 04 мая 2011

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

Но сначала есть логикаошибка в исходной функции.Он слепо выполняет числовую замену, которая приводит к ошибочным результатам, когда ШИРИНА точно равна половине ВЫСОТЫ, например, учитывая следующее:

<img src = "/" width="10" height="20" />

Исходная опубликованная программа возвращает следующий ошибочный результат:

<img src = "/" width="40" height="40" />

Проблема в том, что WIDTH удваивается вдвое.Для обеспечения правильной замены необходима дополнительная логика.

Крутой трюк с регулярными выражениями, которого вы, возможно, не знаете:

Вот модифицированная версия исходной программы, которая исправляет вышеупомянутую ошибку и включает в себя (прокомментировано) версия улучшенного регулярного выражения:

import re
s = '<img src = "/" width="10" height="111"  />'

def a(x):
    b = x.group(0)
    if x.group(1):
        b = b.replace(x.group(1),
            "width=\""+ str(int(x.group(2))*2) +"\"")
    if x.group(3):
        b = b.replace(x.group(3),
            "width=\""+ str(int(x.group(4))*2) +"\"")
    return b

reobj = re.compile(r'''
    <img                        # Start of IMG tag.
    (?:                         # Group for multiple attributes.
      \s+                       # Attributes separated by whitespace.
      (?:                       # Group for attribute alternatives.
        (width\s*=\s*"(\d+)")   # $1: WIDTH attribute, $2 value.
      | (height\s*=\s*"(\d+)")  # $3: HEIGHT attribute, $4 value.
      |[^\s>]+)                 # Other IMG attributes.
    )+                          # One or more attributes.
    [^>]*>                      # End of IMG tag.
    ''', re.IGNORECASE | re.VERBOSE)

ss = re.sub(reobj, a, s)

print ss

Обратите внимание, что WIDTH попадает в группы $ 1 и $ 2, а HEIGHT в группы $ 3 и $ 4, даже если их порядок в целевой строке меняется на обратный.Хотел бы я сказать, что я придумал этот крутой трюк, но я этого не сделал.Я украл его из одного из отличных постов Стивена Левитана: Получение нескольких необязательных значений атрибутов HTML .Довольно изящно, а?

Более чистое решение для регулярных выражений

Как бы умно это ни было, оно все же сложнее, чем нужно для этой работы.Я хотел бы сделать это простым и просто сделать две отдельные операции замены следующим образом:

import re
s = '<img src = "/" width="10" height="111"  />'

def a(x):
    return x.group(1) + str(int(x.group(2))*2)

ss = re.sub(r"(?i)(<img[^>]*?width\s*=\s*[\"'])(\d+)",a, s)
ss = re.sub(r"(?i)(<img[^>]*?height\s*=\s*[\"'])(\d+)",a, ss)

print ss

Меньше.чище, легче для чтения и, вероятно, самое быстрое решение.(Обратите внимание, что функция обратного вызова становится тривиальной.)

2 голосов
/ 04 мая 2011

Не используйте регулярные выражения при работе с HTML .Выполните синтаксический анализ, например, lxml .

import lxml.html

html = '<img src = "werwerwe" height="111" width="10" />'

etree = lxml.html.fromstring(html)

images = etree.xpath('//img')
for image in images:
    h = int(image.attrib['height'])
    w = int(image.attrib['width'])
    image.attrib['height'] = str(h*2)
    image.attrib['width'] = str(w*2)

print lxml.html.tostring(etree)

Дает:

<img src="werwerwe" height="222" width="20">

1 голос
/ 04 мая 2011

Еще раз , эта задача должна быть полностью решена парсером HTML, как предложено здесь и здесь .


Если вы все еще хотите использовать регулярные выражения для этой цели, вы можете использовать это вместо:

<img.*?(width|height)=\"(\d+)\".*?(width|height)=\"(\d+)\"

Например:

В тексте: <img src = "/" width="10" height="111"/> будет соответствовать следующим группам:

  • Группа 1: "width"
  • Группа 2: "10"
  • Группа 3: "height"
  • Группа 4: "111"

В тексте: <img src = "/" height="111" width="10"/> будет соответствовать:

  • Группа 1: "height"
  • Группа 2: "111"
  • Группа 3: "width"
  • Группа 4: "10"

Теперь он совпадает независимо от того, является ли width предшествующим height или наоборот, и я думаю, что 4 группы дают вам достаточно информации при выполнении замены.

Редактировать:
Я захватил группы height и width, чтобы вы знали, какое значение соответствует первому (в противном случае, если вы получите 111 и 10, вы не будете знать, какие из них height и width), но я не думаю, что это необходимо в вашем случае, потому что все, что вам нужно сделать, это дублировать оба значенияes , но может быть полезно, если вы хотите увеличить height и width на разные значения.

1 голос
/ 04 мая 2011

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

Итак, используйте html-парсер, такой как HTMLParser в python, он будет декодировать весь текст HTML, и вам просто нужно распечатать его обратно с вашими изменениями.

В другой заметке, изменив html, напримерВы делаете выглядит подозрительно.Вы, вероятно, делаете что-то очень трудным путем.

0 голосов
/ 04 мая 2011

Попробуйте использовать следующее регулярное выражение:

<img.*?height=\"(\d+)\".*?width=\"(\d+)\"

Group 1 захватит высоту и Group 2 ширина

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