2016-09-21 2 views
2

Ich benutze reguläre Ausdrücke auf einer Reihe von Wikipedia-Seiten. Wirklich gut für den ersten arbeiten wie 20 Seiten, aber dann friert es plötzlich ein, ohne dass ich einen Grund sehe. dies liefert das Skript zu unterbrechen:Python Regex friert mit kleinen Eingabe String

File "imageListFiller.py", line 30, in getImage 
foundImage = re.search(urlRegex, str(decodedLine)) 
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/re.py",line 173, in search 
return _compile(pattern, flags).search(string) 

dies ist mein Code:

def getImage(wikiHtml): 
    urlRegex = """File:((?:[a-zA-Z]|[0-9]|[[email protected]&+]|[!*\(\),]|(?:[0-9a-fA-F][0-9a-fA-F]))*?\.(png|jpg|svg|JPG))""" 
uselessPictures = ("Wiktionary-logo-v2.svg", "Disambig_gray.svg", 
        "Question_book-new.svg", "Commons-logo.png")  

for line in wikiHtml: 
    decodedLine = line.decode('utf-8') 
    foundImage = re.search(urlRegex, str(decodedLine)) 
    if foundImage: 
     if not foundImage.group(1) in uselessPictures: 
      return foundImage.group(1) 

und dies ist die Eingabezeichenfolge, die es zum Einfrieren verursacht:

href = "/ wiki/File: EARTH _-_ WIKIPEDIA_SPOKEN_ARTICLE_ (Part_01) .ogg "title =" Diesen Artikel anhören "> src =" // upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon.svg/20px-Sound-icon .svg.png "width =" 20 "height =" 15 "srcset =" // upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon.svg/30px-Sound-ic on.svg.png 1.5x, //upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon.svg/40px-Sound-icon.svg.png 2x "data-file-width =" 128 "data-file-height =" 96 "> />

Die Regex soll hier eigentlich nicht übereinstimmen, sie muss nur diese Zeile überspringen. Danke!

+0

Gerade FYI: Beachten Sie, dass '[-_ $]' entsprechen alle Großbuchstaben ASCII-Buchstaben und Ziffern und mehr . Wenn Sie dem Bindestrich entkommen, wird es schon viel sicherer. –

+0

Sie (oder besser Ihr Ausdruck) neigen zu katastrophalem Backtracking: https://regex101.com/r/eH4nJ2/1 – Jan

+1

Warum nicht einfach '([^ /] * \. (Png | jpg | svg | JPG)) ' – fabianegli

Antwort

1

Der $-_ Teil in Ihrem Muster hat einen Bereich erzeugt, der Großbuchstaben und Ziffern und noch mehr Zeichen enthält. Da andere alternative Zweige in der Gruppe am gleichen Ort übereinstimmen könnten (wie [a-zA-Z]), führte dies zu einem Timeout-/katastrophalen Backtracking-Problem.

Sie müssen nur concat alle Charakterklassen, die nur in der 1. Gruppe 1 Zeichen übereinstimmen, und entweder die - innerhalb der Zeichenklasse entkommen oder sich zu Beginn/Ende der Zeichenklasse setzen (ich noch würde entkommen es, wenn das Muster in Zukunft aktualisiert werden soll):

r"""File:((?:[0-9a-fA-F]{2}|[a-zA-Z0-9\[email protected]&+!*(),])*?\.(png|jpg|svg|JPG))""" 

Siehe regex demo.

Auch sollte die längere Alternative der kürzeren vorausgehen, also sollte die [0-9a-fA-F]{2} zuerst gehen.

Auch kann \w verwendet werden, um das Muster ein wenig zu verkürzen ([a-zA-Z0-9_] zu ersetzen):

r"""File:((?:[0-9a-fA-F]{2}|[\w\[email protected]&+!*(),])*?\.(png|jpg|svg|JPG))""" 
          ^^^