2016-05-03 20 views
2

Ich habe eine Website, die ich versuche zu kratzen (obwohl nicht wirklich verstehen, HTML), aber ich habe eine Menge gelesen und machte einige Fortschritte. Es ist eine schmutzige Seite, aber der wichtige Teil sieht wie folgt aus:HTML Parsing mit Lxml, Python, .tail von <br> Tags

<h1> 
    <b>DESCRIPTOR1: </b> 
     " important content " 
    <br> 
    <b>DESCRIPTOr2: </b> 
     " important content" 
    <hr> 
</h1> 

<b>Title1</b> 
    " A lot of important text" 
<br> 
<br> 
<b>Title2</b> 
    "A lot of important text" 
<br> 
<br> 
<b>Title3</b> 
<br> 
    "1. List of text pertaining to Title3 " 
<br> 
    "2. List of items for Title 3" 
<br> 
    "3. the number of listed items is variable for every page" 
<br> 
    "4. Sometimes no list at all" 
<br> 
<br> 
<b> Next Title: </b> 

....and so on 

Jetzt kann ich zu ziemlich nahe kommen, was ich meine Endergebnis will Ausnahme sein, wenn ich zum Titel erhalte 3 und es gibt ein <br> vor dem Inhalt

import lxml.html 

htmltree = lxml.html.parse('sample.html') 

items = htmltree.xpath('//*[@id="sampletext"]/b') 

for node in items: 

    print (node.text.strip()) 
    print node.tail 

Jetzt sind meine 2 Probleme (1): das geht mit Titel 3. Dies ist, wie ich es bin ich nicht näher Whitespaces Streifen aus kann aus den .tail's und (2): ich erhalte „None“ zurückgegeben für Title3, weil es keine .tail vor dem nächsten Element gibt, das eine <br> ist. Idealerweise wäre ich in der Lage, jeden Text zwischen Element-Tags zu addieren, bis ich zu meinem nächsten Identifikator-Tag komme, der in diesem Fall <b> ist. Hoffnung, die Sinn macht. Irgendwelche Hinweise bitte?

Antwort

2

Sie können versuchen, den folgenden XPath-Ausdruck mit:

for item in items: 
    result = item.xpath('following-sibling::text()[normalize-space()][preceding-sibling::b[1] = $b]', b=item) 
    print [r.strip() for r in result] 

Ausgang, wenn gegen HTML-Schnipsel in Frage geprüft:

['" A lot of important text"'] 
['"A lot of important text"'] 
['"1. List of text pertaining to Title3 "', '"2. List of items for Title 3"', '"3. the number of listed items is variable for every page"', '"4. Sometimes no list at all"'] 
[] 

Kurze Erklärung über die XPath:

  • following-sibling::text()[normalize-space()]: Finden Sie nicht leer ist, folgender Geschwister Textknoten ...
  • [preceding-sibling::b[1] = $b]: ... wo das nächste preceding-sibling b Element $b entspricht. $b ist ein XPath-Parameter, der in den obigen Codes durch den aktuellen item ersetzt wird. Dies wird angezeigt durch den 2. Parameter xpath() Methode (b=item)
+0

Vielen Dank. Ich verstehe es (noch) nicht, sondern versuche es. Die Druckzeile ist auch verwirrend für mich. Dies funktioniert gut für die Fälle, wo ich alles bis zum nächsten 'b' Element haben möchte, auch wenn es durch Pausen getrennt ist, aber es gibt ein paar Fälle, wo ich nur die unmittelbaren Sachen nach 'b' und nicht den anderen Text möchte. Ich will nur alles bis zum nächsten 'b', während ich 'br' ignoriere, wenn es eine nummerierte Liste ist. Jeder einfache Weg, das zu tun? –