2016-07-27 9 views
1

Wie extrahiere ich alle Kommentare im HTML-Stil aus einem Dokument mit Python?HTML-Kommentare in Python mit regex oder lxml extrahieren?

Ich habe versucht, eine Regex:

text = 'hello, world <!-- comment -->' 
re.match('<!--(.*?)-->', text) 

Aber es produziert nichts. Ich verstehe das nicht, da die gleiche Regex funktioniert in der gleichen Zeichenfolge bei https://regex101.com/

UPDATE: Mein Dokument ist eigentlich eine XML-Datei, und ich Parsing das Dokument mit Pyquery (basierend auf Lxml), aber ich don glaube nicht, dass lxml kann extract comments that aren't inside a node. Dies ist, was das Dokument wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?> 
<clinical_study rank="220398"> 
    <intervention_browse> 
    <!-- CAUTION: The following MeSH terms are assigned with an imperfect algorithm --> 
    <mesh_term>Freund's Adjuvant</mesh_term> 
    <mesh_term>Keyhole-limpet hemocyanin</mesh_term> 
    </intervention_browse> 
    <!-- Results have not yet been posted for this study        --> 
</clinical_study> 

UPDATE 2: Vielen Dank für die andere Antwort darauf hindeutet, aber ich bin das Dokument bereits ausgiebig mit lxml Parsen und will nicht alles mit BeautifulSoup neu zu schreiben. Habe Titel entsprechend aktualisiert.

+1

Dies wäre trivial und zuverlässiger mit lxml oder beautifulsoup –

+0

@MaxU Ich benutze bereits lxml (pyquery), also möchte ich nicht wirklich zu BeautifulSoup wechseln, aber danke. Ich habe die Frage aktualisiert, um klar zu sein, dass ich glücklich bin, regex oder lxml zu verwenden. – Richard

+0

@Padraic Ich bin mir nicht sicher, ob es tatsächlich in Lxml möglich ist, siehe das Update. – Richard

Antwort

1

Dies scheint für mich den Kommentar zu drucken:

from lxml import etree 
txt = """<?xml version="1.0" encoding="UTF-8"?> 
<clinical_study rank="220398"> 
    <intervention_browse> 
    <!-- CAUTION: The following MeSH terms are assigned with an imperfect algorithm --> 
    <mesh_term>Freund's Adjuvant</mesh_term> 
    <mesh_term>Keyhole-limpet hemocyanin</mesh_term> 
    </intervention_browse> 
    <!-- Results have not yet been posted for this study        --> 
</clinical_study>""" 
root = etree.XML(txt) 
print root[0][0] 

enter image description here

Um den letzten Kommentar zu erhalten:

comments = [itm for itm in root if itm.tag is etree.Comment]: 
if comments: 
    print comments[-1] 
+0

Danke! Es ist eigentlich der letzte Kommentar, der mir wichtig ist (in einem Dokument mit einer beliebigen Anzahl von Kommentaren, obwohl der letzte Kommentar immer kurz vor dem schließenden 'clinical_study' -Tag steht), eine Idee, wie du das bekommen würdest? – Richard

+0

Ah 'root [0]' scheint es zu tun. Vielen Dank! – Richard

+0

'root [1]' druckt die '' für mich. –

0

Sie könnten schöne Suppe verwenden den Kommentar in einer for-Schleife zu extrahieren wie diese

from bs4 import BeautifulSoup, Comment 

text = 'hello, world <!-- comment -->' 

soup = BeautifulSoup(text, 'lxml') 

for x in soup.findAll(text=lambda text:isinstance(text, Comment)): 
    print(x) 
0

ändern match-search einem dann:

text = 'hello, world <!-- comment -->' 
comment = re.search('<!--(.*?)-->', text) 
comment.group(1) 

Ausgang:

' comment ' 
1

Sie muss die re.findall() -Methode verwenden, um alle übereinstimmenden Teilstrings zu extrahieren ein bestimmtes Muster.

re.match() überprüft nur, ob das Muster am Anfang der Zeichenfolge passt, während re.search() nur die erste Übereinstimmung innerhalb der Zeichenfolge liefert. Für Ihren Zweck ist re.findall() definitiv die richtige Methode und sollte bevorzugt werden.