Seite 1 von 1

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

Verfasst: Dienstag 22. April 2025, 22:17
von python_m
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!

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

Verfasst: Donnerstag 24. April 2025, 19:49
von Sirius3
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.

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

Verfasst: Donnerstag 24. April 2025, 22:45
von __blackjack__
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.

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

Verfasst: Donnerstag 24. April 2025, 23:41
von __blackjack__
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()