2016-05-13 12 views
0

Ich habe eine Testbericht-Datei von Nose im HTML-Format. Ich möchte einige Teile des Textes daraus in Python extrahieren. Ich werde dies in einer E-Mail im Nachrichtenteil senden.Python, wie Inhalte aus HTML-Datei extrahieren

Ich habe folgendes Beispiel:

<!DOCTYPE html> 
<html> 
<head> 
    <title>Unit Test Report</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 

<style> 
body { 
    font-family: Calibri, "Trebuchet MS", sans-serif; 
} 
* { 
    word-break: break-all; 
} 
table, td, th, .dataid { 
    border: 1px solid #aaa; 
    border-collapse: collapse; 
    background: #fff; 
} 
section { 
    background: rgba(0, 0, 0, 0.05); 
    margin: 2ex; 
    padding: 1ex; 
    border: 1px solid #999; 
    border-radius: 5px; 
} 
h1 { 
    font-size: 130%; 
} 
h2 { 
    font-size: 120%; 
} 
h3 { 
    font-size: 100%; 
} 
h4 { 
    font-size: 85%; 
} 
h1, h2, h3, h4, a[href] { 
    cursor: pointer; 
    color: #0074d9; 
    text-decoration: none; 
} 
h3 strong, a.failed { 
    color: #ff4136; 
} 
.failed { 
    color: #ff4136; 
} 
a.success { 
    color: #3d9970; 
} 
pre { 
    font-family: 'Consolas', 'Deja Vu Sans Mono', 
       'Bitstream Vera Sans Mono', 'Monaco', 
       'Courier New', monospace; 
} 

.test-details, 
.traceback { 
    display: none; 
} 
section:target .test-details { 
    display: block; 
} 

</style> 
</head> 
<body> 
    <h1>Overview</h1> 
    <section> 
     <table> 
      <tr> 
       <th>Class</th> 
       <th class="failed">Fail</th> 
       <th class="failed">Error</th> 
       <th>Skip</th> 
       <th>Success</th> 
       <th>Total</th> 
      </tr> 
       <tr> 
        <td>Regression_TestCase.RegressionProject_TestCase2.RegressionProject_TestCase2</td> 
        <td class="failed">1</td> 
        <td class="failed">9</td> 
        <td>0</td> 
        <td>219</td> 
        <td>229</td> 
       </tr> 
      <tr> 
       <td><strong>Total</strong></td> 
       <td class="failed">1</td> 
       <td class="failed">9</td> 
       <td>0</td> 
       <td>219</td> 
       <td>229</td> 
      </tr> 
     </table> 
    </section> 
    <h1>Failure details</h1> 
      <section> 
       <h2>Regression_TestCase.RegressionProject_TestCase2.RegressionProject_TestCase2 (1 failures, 9 errors)</h2> 
       <div> 
         <section id="Regression_TestCase.RegressionProject_TestCase2.RegressionProject_TestCase2:test_00010_import_user_invalid_credentials"> 
          <h3>test_00010_import_user_invalid_credentials: <strong>selenium.common.exceptions.NoSuchElementException</strong></h3> 
          <div class="test-details"> 
           <h4>Traceback</h4> 
           <pre class="traceback">Traceback (most recent call last): 
    File "C:\Python27\lib\unittest\case.py", line 329, in run 
    testMethod() 
    File "C:\test_runners\selenium_regression_test_5_1_1\ClearCore - Regression Test\Regression_TestCase\RegressionProject_TestCase2.py", line 221, in test_00010_import_user_invalid_credentials 
    Globals.login_password_invalid) 
    File "C:\test_runners\selenium_regression_test_5_1_1\ClearCore - Regression Test\Pages\security.py", line 51, in enter_invalid_userid_and_password 
    self.enter_user_id(userid) 
    File "C:\test_runners\selenium_regression_test_5_1_1\ClearCore - Regression Test\Pages\security.py", line 32, in enter_user_id 
    user_id_element = self.get_element(*MainPageLocators.security_user_id_textfield_xpath) 
    File "C:\test_runners\selenium_regression_test_5_1_1\ClearCore - Regression Test\Pages\base.py", line 40, in get_element 
    element = self.driver.find_element(by=how, value=what) 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 712, in find_element 
    {'using': by, 'value': value})['value'] 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 201, in execute 
    self.error_handler.check_response(response) 
    File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response 
    raise exception_class(message, screen, stacktrace) 
NoSuchElementException: Message: Message: Unable to find element with xpath == //span[@class="gwt-InlineLabel marginbelow myinlineblock" and contains(text(), "User ID (including domain)")]/following-sibling::input 

-------------------- >> begin captured stdout << --------------------- 
*** Test import_invalid_user_credentials *** 
05_12_1616_49_42 
//span[@class="gwt-InlineLabel marginbelow myinlineblock" and contains(text(), "User ID (including domain)")]/following-sibling::input 
Element not found 
Message: Unable to find element with xpath == //span[@class="gwt-InlineLabel marginbelow myinlineblock" and contains(text(), "User ID (including domain)")]/following-sibling::input 

05_12_1616_51_54 

--------------------- >> end captured stdout << ---------------------- 
---- 
# There is more html below. I have not included everything. It will be too long otherwise. 

Wenn ich die Datei im Browser öffne die Formatierung wie folgt aussieht: Dies ist der Text, den ich aus der HTML-Datei extrahieren möchte.

Class    Fail Error Skip Success  Total 
Regression_TestCase  1 9  0  219   229 

Wie kann ich das bitte tun? Es wäre schön, es in einem Tabellenformat zu halten. Danke, Riaz

+0

Haben Sie irgendwas mit einer XML-Parsing-Bibliothek versucht? (wie https://docs.python.org/2.7/library/xml.etree.elementtree.html#module-xml.etree.ElementTree) – zezollo

+0

Ich schaute auf Beautiful Soup http://stackoverflow.com/questions/16835449/python-beautifulsoup-extract-text-between-element –

+0

In welchem ​​Format soll die Ausgabe sein? Möchten Sie, dass es wie eine Tabelle in Excel aussieht (z. B. CSV) oder möchten Sie eine Textdatei mit diesen Zeilen, Spalten und Abständen? – kaisquared

Antwort

1

Ihr Beispiel-HTML-Code enthält nicht geschlossene Tags und schließende Tags ohne öffnende Tags. Ich nehme an, Sie sind nur ein Beispiel zeigen, und dass, dass die Datei, die Sie wie unten wohlgeformt extrahieren:

<body> 
    <h1>Overview</h1> 
    <section> 
     <table> 
      <tr> 
       <th>Class</th> 
       <th class="failed">Fail</th> 
       <th class="failed">Error</th> 
       <th>Skip</th> 
       <th>Success</th> 
       <th>Total</th> 
      </tr> 
       <tr> 
        <td>Regression_TestCase</td> 
        <td class="failed">1</td> 
        <td class="failed">9</td> 
        <td>0</td> 
        <td>219</td> 
        <td>229</td> 
       </tr> 
      <tr> 
       <td><strong>Total</strong></td> 
       <td class="failed">1</td> 
       <td class="failed">9</td> 
       <td>0</td> 
       <td>219</td> 
       <td>229</td> 
      </tr> 
     </table> 
    </section> 
</body> 

Sie können die etree Modul verwenden Sie den Code als XML zu analysieren. BEARBEITEN: Die Methode geändert, die verwendet wurde, um die Tabelle zu finden, um Xpath zu verwenden, und es so gemacht, dass die Spalte "Summe" nicht gedruckt wird.

BEARBEITEN 2: Ich habe jetzt reguläre Ausdrücke verwendet, um alle Tabellen im Code zu extrahieren. Seien Sie vorsichtig damit, da es eine sehr zerbrechliche Lösung ist. Wenn es ein offenes Tabellen-Tag ohne ein schließendes Tabellen-Tag gibt, dann wird es den gesamten Text nach dem Tag der offenen Tabelle extrahieren und abstürzen, weil die resultierende Zeichenkette nicht wohlgeformt sein wird.

import csv 
import re 
import xml.etree.ElementTree as ET 

# Extract well formed tables 
start = re.compile(r"<table>", re.IGNORECASE) 
end = re.compile(r"</table>", re.IGNORECASE) 
html_code = "" 
table = False 
with open('sample2.xml') as xmlfile: 
    for line in xmlfile: 
     if not table: 
      table = start.search(line) 
      if table: 
       html_code += line 
     else: 
      if end.search(line): 
       html_code += line[0:end.search(line).end()] 
       table = False 
      else: 
       html_code += line 
       table = not end.search(line)    
print html_code 

# Parse html code into Etree Element object 
root = ET.fromstring(html_code) 
elements = root.findall(".//tr") 
print elements 
row = [] 
with open('output.csv', 'wb') as csvfile: 
    csvwriter = csv.writer(csvfile, delimiter=',', quotechar='"') 
    for tablerow in elements: 
     # Only write result to file if there is text inside the first column 
     if list(tablerow)[0].text: 
      for col in list(tablerow): 
       row.append(col.text) 
      csvwriter.writerow(row) 
      print row 
      row = [] 

Wenn Sie öffnen "output.csv" mit Excel, werden Sie Ihren Tisch. Wenn Sie diese Methode verwenden, beachten Sie bitte die Sicherheitswarnungen in der Dokumentation (Link in zezollos Kommentar).

Alternativ können Sie reguläre Ausdrücke verwenden, aber ich bin zu müde, um eine andere Lösung zu schreiben. Vielleicht morgen oder jemand anders könnte so freundlich sein, eine alternative Lösung anzubieten.

+0

Wenn ich meine HTML-Datei analysieren, erhalte ich den Fehler xml.etree.ElementTree.ParseError: nicht wohlgeformt (ungültiges Token): Zeile 125, Spalte 47 –

+0

Der Code zum Analysieren der HTML-Datei lautet: tree = ET.parse (r "E: \ SeleniumTestReport.html") –

+0

Haben alle öffnenden Tags in Ihrem HTML-Code schließende Tags (und umgekehrt)? Wie bei Ihrem zweiten Kommentar geht mein Code davon aus, dass sich die HTML-Datei im selben Verzeichnis wie das Python-Skript befindet. Wenn Sie Ihre HTML-Datei in einem anderen Verzeichnis abgelegt haben, muss der Pfad, den Sie zum Parsen verwenden, natürlich anders sein. – kaisquared

Verwandte Themen