Regex для XML документа - PullRequest
0 голосов
/ 02 мая 2020

Я пытаюсь найти регулярное выражение для документа XML, который по сути является файлом DA SH mpd. В этом случае XML документ имеет тег AdaptationSet, который, в свою очередь, может иметь несколько тегов представления, как показано. Мне нужно сопоставить все теги представления, которые имеют атрибут bandwidth больше указанного ввода, т.е. 2000000 или 4000000 , показанных ниже. Я мог бы придумать следующий, но это не относится к случаю, когда атрибуты занимают несколько строк, как показано в представлении с id = 1 .

RANGE в регулярном выражении может принимать любое значение из 1-9, который можно считать в целочисленном формате, готовом к использованию регулярным выражением. RANGE со следующими 6 цифрами сделает соответствие для значения полосы пропускания 1000000, 2000000 или 3000000 и т. Д. В зависимости от того, равно ли значение RANGE 1 или 2 или 3 соответственно.

regex:

<[Rr]epresentation.*?[Bb]andwidth="0?[%(RANGE)]\d{6}"[\s\S]*?[Rr]epresentation>

    <AdaptationSet segmentAlignment="true" maxWidth="1280" maxHeight="720" maxFrameRate="24" par="16:9">
     <Representation id="1" 
        mimeType="video/mp4" 
        codecs="avc1.4d401f" 
        width="512" 
        height="288" 
        frameRate="24" 
        sar="1:1" 
        startWithSAP="1" 
        bandwidth="1000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
      </Representation>
      <Representation id="2" mimeType="video/mp4" codecs="avc1.4d401f" width="512" height="288" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="2000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
      </Representation>
      <Representation id="3" mimeType="video/mp4" codecs="avc1.4d401f" width="768" height="432" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="4000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_768_1440K_video_$Number$.mp4" startNumber="1" initialization="BBB_768_1440K_video_init.mp4" />
      </Representation>
    </AdaptationSet>

Ответы [ 4 ]

1 голос
/ 12 мая 2020

Вы можете использовать это регулярное выражение

<[Rr]epresentation[^>]*?[Bb]andwidth="0?[2-9]\d{6}"[\s\S]*?[Rr]epresentation>

https://regex101.com/r/MmUkzc/9

1 голос
/ 03 мая 2020

Обновление

Я бы порекомендовал версию ElementTree внизу. Но вот версия регулярного выражения в соответствии с запросом:

import re

txt = """
 <AdaptationSet segmentAlignment="true" maxWidth="1280" maxHeight="720" maxFrameRate="24" par="16:9">
     <Representation id="1" 
        mimeType="video/mp4" 
        codecs="avc1.4d401f" 
        width="512" 
        height="288" 
        frameRate="24" 
        sar="1:1" 
        startWithSAP="1" 
        bandwidth="1000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
      </Representation>
      <Representation id="2" mimeType="video/mp4" codecs="avc1.4d401f" width="512" height="288" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="2000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
      </Representation>
      <Representation id="3" mimeType="video/mp4" codecs="avc1.4d401f" width="768" height="432" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="4000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_768_1440K_video_$Number$.mp4" startNumber="1" initialization="BBB_768_1440K_video_init.mp4" />
      </Representation>
    </AdaptationSet>
"""

input=2000000

reps = re.findall(r'<\s*representation(?:\s*\w+="[^"]*")*\s*>.*?<\/\s*representation\s*>',
    txt, flags=re.IGNORECASE + re.DOTALL)


for rep in reps:
    bandwidth = int(re.search(r'bandwidth="([^"]*)"', rep, flags=re.IGNORECASE).group(1))
    if (bandwidth > input):
        print(rep)

Я думаю, что это проще сделать за пару шагов:

  1. Разделить на Representation одним. Приведенное выше регулярное выражение делает это, но вы, вероятно, могли бы заменить часть соответствия атрибутов (часть в группе без захвата (?:\s*\w+="[^"]*")*\s*>) на что-то более простое, например [^>]*?>, так как вам просто нужен весь элемент представления и его дочерние элементы. Чтобы разбить полное регулярное выражение:

    • <\s* - соответствует <, за которым следуют 0 или более пробелов
    • representation - очевидно, representation. Флаг IGNORECASE гарантирует, что это соответствует вариациям регистра
    • (?:\s*\w+="[^"]*")* - это соответствует нулю или более атрибутов формы blab_blah="value123", включая пробелы вокруг них. (?: означает, что это группа без захвата, поэтому впоследствии она недоступна для метода python group(). Это просто ради повторения, ie, ноль или более атрибутов или (?:...)*. Опять же, поскольку здесь вам не нужно соответствие атрибутов, это можно упростить до чего-то вроде [^>]*?>, но это работает для меня.
    • \s*> - пробелы, за которыми следует >
    • .*? - куча содержимого внутри элемента (включая символы новой строки из-за флага DOTALL), но с анти-жадным соответствием, поэтому мы обязательно останавливаемся на первом встречающемся закрывающем теге и не сопоставляемся с последующим .
    • <\/\s*representation\s*> - закрывающий тег с необязательным пробелом
  2. Как только у нас есть каждый элемент «представления», мы можем вывести полосу пропускания в первый класс python целое число, чтобы его было легче сравнивать с входным

  3. Фильтром на основе значения пропускной способности.

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

Также обратите внимание, что если нет (или более 1) экземпляров атрибута пропускной способности, код не не справиться с этим. Возможно, есть и другие хрупкие аспекты ...

А вот версия, использующая ElementTree. Причина, по которой это в целом лучше, заключается в том, что вы не зависите от своей собственной способности анализировать подробности всех возможных комбинаций XML грамматики. Использование библиотеки означает, что они уже продумали все эти вещи, и все, что вам нужно сопоставить, это маленькие кусочки, такие как имена элементов и атрибутов, поэтому вероятность того, что код сломается, будет меньше. Но, может быть, это домашнее задание или что-то в этом роде ...

import xml.etree.ElementTree as ET

input = 4000
tree = ET.parse('content.xml')
root = tree.getroot()
nodes = [n for n in root.findall('Representation') if int(n.attrib['bandwidth']) >= input]
print(nodes)
0 голосов
/ 10 мая 2020

Учитесь на коде вашего и Эдварда. Но я не рекомендую использовать разбор регулярных выражений XML напрямую.

n = '4'
reg = '<[Rr]epresentation.*?[Bb]andwidth="(['+n+'-9]\d{6}|\d{8})[\d]*"[\s\S]*?</[Rr]epresentation>'

Приведите пример использования SimplifiedDo c.

from simplified_scrapy import SimplifiedDoc
html = '''Your xml'''
doc = SimplifiedDoc(html)
n = '4'
Representations = doc.selects('Representation|representation').containsReg('(['+n+'-9]\d{6}|\d{8})[\d]*',attr='bandwidth')
print(Representations)

Результат:

[{'id': '3', 'mimeType': 'video/mp4', 'codecs': 'avc1.4d401f', 'width': '768', 'height': '432', 'frameRate': '24', 'sar': '1:1', 'startWithSAP': '1', 'bandwidth': '4000000', 'tag': 'Representation', 'html': '\n        <SegmentTemplate timescale="12288" duration="61440" media="BBB_768_1440K_video_$Number$.mp4" startNumber="1" initialization="BBB_768_1440K_video_init.mp4" />\n    '}]
0 голосов
/ 07 мая 2020

Попробуйте более надежный RegEx

Ввод:
диапазон 1 - 9

Выход:
bw [0] содержит целое элемент open to close
bw [2] содержит полосу пропускания

>>> import re
>>>
>>> range = "2"
>>>
>>> regx = r"(?s)(<[Rr]epresentation(?=\s)(?=(?:[^>\"']|\"[^\"]*\"|'[^']*')*?(?<=\s)[Bb]andwidth\s*=\s*(?:(['\"])\s*0*([" + \
...        range + \
...        r"-9]\d{6}|[1-9]\d{7,17})\s*\2))(?=(\s+(?:\".*?\"|'.*?'|[^>]*?)+>))\4(?<!/>).*?</[Rr]epresentation\s*>)"
>>>
>>> txt = """
...  <AdaptationSet segmentAlignment="true" maxWidth="1280" maxHeight="720" maxFrameRate="24" par="16:9">
...      <Representation id="1"
...         mimeType="video/mp4"
...         codecs="avc1.4d401f"
...         width="512"
...         height="288"
...         frameRate="24"
...         sar="1:1"
...         startWithSAP="1"
...         bandwidth="1000000">
...         <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
...       </Representation>
...       <Representation id="2" mimeType="video/mp4" codecs="avc1.4d401f" width="512" height="288" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="2000000">
...         <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
...       </Representation>
...       <Representation id="3" mimeType="video/mp4" codecs="avc1.4d401f" width="768" height="432" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="4000000">
...         <SegmentTemplate timescale="12288" duration="61440" media="BBB_768_1440K_video_$Number$.mp4" startNumber="1" initialization="BBB_768_1440K_video_init.mp4" />
...       </Representation>
...     </AdaptationSet>
... """
>>>
>>> bands = re.findall( regx, txt )
>>> for bw in bands:
...     print ( bw[2] + " : " )
...     print ( bw[0] )
...     print ( "" )
...
2000000 :
<Representation id="2" mimeType="video/mp4" codecs="avc1.4d401f" width="512" height="288" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="2000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_512_640K_video_$Number$.mp4" startNumber="1" initialization="BBB_512_640K_video_init.mp4" />
      </Representation>

4000000 :
<Representation id="3" mimeType="video/mp4" codecs="avc1.4d401f" width="768" height="432" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="4000000">
        <SegmentTemplate timescale="12288" duration="61440" media="BBB_768_1440K_video_$Number$.mp4" startNumber="1" initialization="BBB_768_1440K_video_init.mp4" />
      </Representation>

>>>
...