2010-07-31 12 views

Antwort

8

Denk darüber in „Stufen“. .. da einige x die Wurzel des Unterbaums ist Sie in Betracht ziehen,

x.findAll(text='price') 

ist die Liste aller Elemente in diesem Teilbaum mit Text 'price'. Die Eltern dieser Elemente dann werden natürlich:

[t.parent for t in x.findAll(text='price')] 

, und wenn Sie nur 'th' diejenigen, deren „namen“ (Tag) behalten wollen, dann natürlich

[t.parent for t in x.findAll(text='price') if t.parent.name=='th'] 

und Sie wollen, dass die „nächsten Geschwister“ von denen, (aber nur, wenn sie sind auch 'th' s), so

[t.parent.nextSibling for t in x.findAll(text='price') 
if t.parent.name=='th' and t.parent.nextSibling and t.parent.nextSibling.name=='th'] 

Hier sehen Sie das Problem mit einer Liste Verständnis mit: zu viel Wiederholung, da wir nicht zuordnen können Zwischenergebnisse zu einfachen Namen. Schalten wir deshalb auf eine gute alte Masche ...:

bearbeiten: hinzugefügt Toleranz für eine Reihe von Text zwischen den Eltern th und dem „nächsten Geschwister“ sowie Toleranz für letztere ein td stattdessen sein, pro OPs Kommentar.

for t in x.findAll(text='price'): 
    p = t.parent 
    if p.name != 'th': continue 
    ns = p.nextSibling 
    if ns and not ns.name: ns = ns.nextSibling 
    if not ns or ns.name not in ('td', 'th'): continue 
    print ns.string 

Ich habe ns.string hinzugefügt, dass die nächsten Geschwister Inhalte geben, wenn und nur wenn sie sind nur Text (keine weiteren verschachtelten Tags) - natürlich Sie weiter an dieser Stelle statt analize kann, hängt davon ab, die Anforderungen Ihrer Anwendung! -). Ähnlich stelle ich mir vor, dass Sie nicht nur print tun, aber etwas schlauer, aber ich gebe Ihnen die Struktur.

Gespräch über die Struktur, die Ankündigung, die zweimal I if...: continue verwenden: Diese Verschachtelung reduziert im Vergleich zu der Alternative der if ‚s Bedingung Invertieren und Einrücken alle folgenden Anweisungen in der Schleife - und‚flach ist besser als nested‘ist einer der Koans im Zen von Python (import this an einer interaktiven Aufforderung, sie alle zu sehen und zu meditieren ;-).

+0

große Antwort Alex, ich habe gerade findAll bisher und jetzt fühle ich kann ich die Dom mit diesem Wissen durchqueren, gehen Python! hehe – Blankman

+0

in der Verbindung 'wenn nicht ns oder ns.name ...', wenn ns ist None dann ns.name wird fehlschlagen nein? – Blankman

+0

eigentlich mein HTML ist wie: Preis $ 99,99 und p.nextSibling ist leer, ich versuchte p.next und das funktioniert auch nicht. – Blankman

0

Mit pyparsing ist es einfach in die Mitte einiger HTML für einen Tag Muster wie folgt zu erreichen:

from pyparsing import makeHTMLTags, Combine, Word, nums 

th,thEnd = makeHTMLTags("TH") 
floatnum = Combine(Word(nums) + "." + Word(nums)) 
priceEntry = (th + "price" + thEnd + 
       th + "$" + floatnum("price") + thEnd) 

tokens,startloc,endloc = priceEntry.scanString(html).next() 

print tokens.price 

Pyparsing der makeHTMLTags Helfer ein Paar pyparsing Ausdrücke gibt, eine für den Start-Tag und eine für das End-Tag Das Start-Tag-Muster ist viel mehr als nur das Hinzufügen von "<>" s um die angegebene Zeichenfolge, sondern ermöglicht auch zusätzliche Leerzeichen, variable Groß-/Kleinschreibung und das Vorhandensein oder Fehlen von Tag-Attributen. Zum Beispiel, beachten Sie, dass, obwohl ich "TH" als Tag der Tabelle Kopf angegeben, es auch "th", "Th", "TH" und "TH" übereinstimmen. Das Standard-Whitespace-Skipping-Verhalten von Pyparsing behandelt auch zusätzliche Leerzeichen zwischen Tag und "$", zwischen "$" und numerischem Preis usw., ohne dass "Null oder mehr Whitespace-Zeichen hierhin gehen" angezeigt werden. Durch die Zuweisung des Ergebnisnamens "price" (nach floatum in der Definition von priceEntry) wird der Zugriff auf diesen spezifischen Wert aus der vollständigen Liste der Tokens, die dem gesamten Ausdruck priceEntry entsprechen, sehr einfach.

(Combine wird für 2 Aufgaben: Er Leerzeichen zwischen den Komponenten der Nummer nicht zulässt, und gibt einen einzigen kombinierten Token „99,99“ anstelle der Liste ["99", ".", "99"].)