HTML-Code Sonderzeichen < und > in Verbindung mit Pandas werden zu &lt; und &gt;

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
python_m
User
Beiträge: 1
Registriert: Dienstag 22. April 2025, 21:58

Hallo zusammen,
vorweg - ich bin relativ neu mit Python unterwegs und bastle an einem Skript, welches
(1) von einer URL Daten im JSON Format abruft
(2) einzelne Attribute filtert
(3) aus den Daten mittel Pandas eine HTML-Tabelle erzeugt
(4) Die HTML-Datei auf einer URL per SFTP bereitstellt

Grundsätzlich klappt das alles schon. Ich wollte nun ein Attribut in Schritt (2) durch Verkettung mit HTML-Code anreichern und habe dabei zwei Probleme:
- zum einen werden die im HTML-Code befindlichen "<" und ">" Zeichen in &lt; und &gt; umgewandelt
- zum anderen möchte ich im HTML-Code ein ein Hex-Farbcode verwenden, z.B. #FFFFF - das "#" Zeichen habe ich daher mit \ escaped. Dadurch kommt es allerdings auch mit dem \ in der HTML Tabelle an...

Hier die relevanten Code Teile:

Code: Alles auswählen

# Schritt 1: JSON von URL abrufen
json_url = 'http://192.168.199.xxx/api/'
response = requests.get(json_url)
response.raise_for_status()  # Fehler prüfen
data = response.json()

# Schritt 2: Benötigte Attribute filtern
filtered_data = []
for entry in data:
    filament_info = entry.get('filament', {})
    vendor_info = filament_info.get('vendor', {})
    name = vendor_info.get('name')
    material = filament_info.get('material')
    farbe = filament_info.get('name')
   farbe_hex = '<div class="color-box" style="background-color: \#' + filament_info.get('color_hex') + ';"></div>;'
    weight_info = str(round(entry.get('remaining_weight'))) + 'g'
    filtered_data.append({'Hersteller': name, 'Material': material, 'Farbe': farbe, 'Farbcode': farbe_hex, 'Gewicht': weight_info})

# Schritt 3: In eine HTML-Tabelle umwandeln
df = pd.DataFrame(filtered_data)
html_table = df.to_html(index=False)
Dies ist die relevante Zeile:

Code: Alles auswählen

 farbe_hex = '<div class="color-box" style="background-color: \#' + filament_info.get('color_hex') + ';"></div>;'
Der HTML Code sieht dann auszugsweise z.B: so aus:

Code: Alles auswählen

<td>&lt;div class="color-box" style="background-color: \#000000;"&gt;&lt;/div&gt;;</td>
So müsste er aussehen:

Code: Alles auswählen

<td><div class="color-box" style="background-color: #000000;"></div>;</td>
Hat jemand eine Idee wie ich das hinbekommen kann?

Wäre für jeden Tipp dankbar!
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Einrückungen sind in Python wichtig. Du hast einen IndentationError im Code.
to_html kennt das Argument `escape`.
Warum denkst Du, dass man ein \ vor # schreiben muß? In aktuellen Python-Versionen ist das inzwischen ein Syntaxfehler.
Strings setzt man nicht per + zusammen, sondern benutzt f-Strings.
Wenn "remaining_weight" nicht im Wörterbuch ist, dann führt round zu einem Fehler.
Benutzeravatar
__blackjack__
User
Beiträge: 13997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich persönlich würde Pandas nicht dazu missbrauchen eine HTML-Tabelle zu erstellen. Dafür ist das ja nicht gedacht. Es gibt Template-Bibliotheken für HTML.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import jinja2
import requests
from attr import field, frozen

template = jinja2.Template(
    """\
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  {# TODO Define CSS used in the body. #}
</head>
<body>
  <table>
    <thead>
      <th>Hersteller</th>
      <th>Material</th>
      <th>Farbe</th>
      <th>Farbcode</th>
      <th>Gewicht (g)</th>
    </thead>
    <tbody>
      {% for entry in entries %}
        <tr>
          <td>{{ entry.vendor_name }}</td>
          <td>{{ entry.material }}</td>
          <td>{{ entry.color }}</td>
          <td>
            <div class="color-box" style="background-color: #{{ entry.hex_color }};"></div>
          </td>
          <td>{{ entry.weight|round|int }}</td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
</body>
</html>
""",
    autoescape=True,
)


@frozen
class Entry:
    vendor_name = field()
    material = field()
    color = field()
    hex_color = field()
    weight = field()

    @classmethod
    def from_json_data(cls, data):
        filament_info = data.get("filament", {})
        return cls(
            filament_info.get("vendor", {}).get("name"),
            filament_info.get("material"),
            filament_info.get("name"),
            filament_info.get("color_hex"),
            data.get("remaining_weight"),
        )


def main():
    response = requests.get("http://192.168.199.xxx/api/", timeout=None)
    response.raise_for_status()
    html_table = template.render(
        entries=map(Entry.from_json_data, response.json())
    )
    ...


if __name__ == "__main__":
    main()
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten