Seite 1 von 1

UnicodeEncodeError

Verfasst: Donnerstag 16. April 2020, 14:56
von kaaniboy68
Hallo,

ich versuche zur Zeit eine HTML Tabelle in eine .csv zu schreiben.

Mein bisheriger Code:

Code: Alles auswählen

from bs4 import BeautifulSoup
import csv

html = open("/Users/kaanekici/Documents/Programmiern/GymHVertretungen/GymHVertretungenHTML.html").read()
soup = BeautifulSoup(html, features='lxml')
table = soup.find(class_="TabelleVertretungen")

output_rows = []
for table_row in table.findAll('tr'):
    columns = table_row.findAll('td')
    # for xtext in columns:
    #     print(xtext.get_text())
    output_row = []
    for column in columns:
        output_row.append(column.text)
    output_rows.append(output_row)

with open('output.csv', 'wb') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(output_rows)
Nach ausführen bekomme ich die Fehlermeldung: "UnicodeEncodeError: 'ascii' codec can't encode characters in position 4-6: ordinal not in range(128)"

Ich weiß nicht, wie ich den Fehler gefixt bekomme; kann mir jemand helfen?

Re: UnicodeEncodeError

Verfasst: Donnerstag 16. April 2020, 15:09
von sparrow
Immer wenn man open verwendet, sollte man auch ein Encoding angeben. Das sollte dein Problem lösen.

Re: UnicodeEncodeError

Verfasst: Freitag 17. April 2020, 11:01
von __blackjack__
@kaaniboy68: Das mit dem Encoding gilt für Textdateien, also so wie das Programm jetzt ist, auch für den HTML-Quelltext der eingelesen wird. Alternativ kann man den auch als Binärdaten einlesen und an `BeautifulSoup` verfüttern.

Auch beim einlesen sollte man die Datei sicher wieder schliessen und sich nicht auf die autmatische Speicherbereinigung verlassen. Also ``with`` auch dort verwenden, oder `pathlib.Path` was eine Methode hat die sich um öffnen, einlesen, schliessen kümmert.

Beim öffnen von Dateien für das `csv`-Modul ist es wichtig ``newline=""`` als Argument anzugeben, sonst kann man damit kaputte CSV-Dateien erzeugen.

Die Schriebweise von `findAll()` entspricht nicht den Namenskonventionen, darum sollte man diese Methode nicht mehr verwenden, sondern `find_all()`. Was übrigens den gleichen Effekt hat wie das `Tag`-Objekt direkt aufzurufen.

Die innere ``for``-Schleife lässt sich leicht als „list comprehension“ ausdrücken. Und wenn man das gemacht hat, sieht man, dass man das dann auch mit der äusseren ``for``-Schleife machen kann.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import csv
from pathlib import Path

from bs4 import BeautifulSoup


HTML_FILE_PATH = Path(
    "/Users/kaanekici/Documents/Programmiern/GymHVertretungen/GymHVertretungenHTML.html"
)


def main():
    soup = BeautifulSoup(HTML_FILE_PATH.read_bytes(), "lxml")
    output_rows = [
        [column.text for column in table_row("td")]
        for table_row in soup.find(class_="TabelleVertretungen")("tr")
    ]
    with open("output.csv", "w", newline="", encoding="utf-8") as csv_file:
        csv.writer(csv_file).writerows(output_rows)


if __name__ == "__main__":
    main()