Spritpreise

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6330
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dienstag 27. April 2021, 20:19

Hier ein billiges Tool zum Auslesen der Spritpreise von clever-tanken.de

Die Anzeige geschieht im Terminal, könnte aber natürlich auch per Mail oder SMS verschickt oder anderweitig eingebettet werden.

Code: Alles auswählen

import bs4
import requests

LOCATION = 45886  # PLZ oder Ort
URL = "https://www.clever-tanken.de/tankstelle_liste"

def get_prices(location, radius=2, sorte=7):
    query = dict(ort=location, r=radius, spritsorte=sorte)
    response = requests.get(URL, query)
    response.raise_for_status()
    soup = bs4.BeautifulSoup(response.text, "html.parser")
    return parse_results(soup)

def parse_results(soup):
    for result in soup.find_all(class_="list-card-container"):
        price = result.find(class_="price-text").text.strip()
        location = ", ".join(
            result.find(class_=f"fuel-station-location-{typ}").text.strip()
            for typ in ("name", "street", "city")
        )
        yield price, location

def main():
    for price, location in get_prices(LOCATION):
        print(f"{location} ({price} €)")

if __name__ == "__main__":
    main()
PythonPeter
User
Beiträge: 5
Registriert: Mittwoch 12. Mai 2021, 20:03

Sonntag 16. Mai 2021, 20:49

Das ist ja mal praktisch, vielen Dank!
Das hilft mir weiter, ich interessiere mich ebenfalls für das Auslesen von Website-Daten.
Wie viel Erfahrung hast du schon in Python? Bin noch recht am Anfang, was glaubst du, wie lange es dauert, bis dass ich das auch hinkriegen kann?

Grüße,
Peter
Benutzeravatar
snafu
User
Beiträge: 6330
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Montag 17. Mai 2021, 18:14

Circa 12 Jahre müssten es inzwischen sein. Aber das heißt nicht viel: Beruflich mache ich etwas kaufmännisches. Das Programmieren in Python ist also ein Hobby, welches ich mal mehr, mal weniger intensiv betreibe. Wie gut du in welcher Zeit werden kannst, lässt sich unmöglich abschätzen. Für Projekte benötigt man ja auch Zusatzwissen, wie hier zB ein Grundverständnis von HTML und von der BeautifulSoup-API. Und wenn der Code am Ende nicht wie Kraut und Rüben aussehen soll, ist natürlich eine gewisses Maß an (Python-)Programmiererfahrung von Vorteil. Aber wie gesagt: Es ist von Person zu Person total unterschiedlich, in welche Richtung man sich beim Programmieren entwickelt. Am meisten helfen Vorhaben, an denen man wirklich Spaß hat und wo somit die Motivation zum Ausprobieren und Dazulernen vorhanden ist.
Benutzeravatar
snafu
User
Beiträge: 6330
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dienstag 18. Mai 2021, 05:52

Verbesserte Version:
- Mehrere Spritsorten zur Auswahl
- Uhrzeit/Datum der Abfrage wird gezeigt
- Anzeige auch von Tankstellen ohne aktuellen Preis (zB wenn nachts geschlossen)

Code: Alles auswählen

from datetime import datetime

import bs4
import requests

LOCATION = 45886  # Ort oder PLZ
RADIUS = 2  # Umkreis in km
FUEL_TYPE = "E5"  # Spritsorte

URL = "https://www.clever-tanken.de/tankstelle_liste"

FUEL_TYPES = {"diesel": 3, "super e5": 7, "super e10": 5, "super plus": 6}

def convert_type(fuel_type):
    if isinstance(fuel_type, int):
        return fuel_type
    for name, value in FUEL_TYPES.items():
        if fuel_type.casefold() in (name, *name.split()):
            return value
    raise ValueError(f"Unknown type: {fuel_type!r}")

def get_prices(location, radius, fuel_type):
    query = dict(ort=location, r=radius,
                 spritsorte=convert_type(fuel_type))
    response = requests.get(URL, query)
    response.raise_for_status()
    return iter_results(response.text)

def iter_results(markup):
    soup = bs4.BeautifulSoup(markup, "html.parser")
    for result in soup.find_all(class_="list-card-container"):
        price = result.find(class_="price").text.strip()
        location = ", ".join(
            result.find(class_=f"fuel-station-location-{typ}").text.strip()
            for typ in ("name", "street", "city")
        )
        yield price, location

def get_header(fuel_type):
    now = datetime.now()
    text = f"Spritpreise ({fuel_type}) am {now:%d.%m.%Y} um {now:%H:%M} Uhr"
    divider = "-" * len(text)
    return f"{text}\n{divider}\n"

def main():
    print(get_header(FUEL_TYPE))
    results = get_prices(LOCATION, RADIUS, FUEL_TYPE)
    for price, location in results:
        print(f"{location} ({price} €)")

if __name__ == "__main__":
    main()
heyJo
User
Beiträge: 17
Registriert: Mittwoch 24. Januar 2018, 20:49
Wohnort: Köln

Freitag 11. Juni 2021, 10:18

Hallo snafu,

vielen Dank für das Tool!

Ich habe es mir um die GPS-Funktionalität von iOS (Pythonista) ergänzt und einen Kurzbefehl angelegt. Jetzt bekomme ich auf Knopfdruck alle Tankstellen/ Preise in meiner aktuellen Umgebung.

Code: Alles auswählen


import requests
import time
import bs4
import location  #iOS Pythonista Modul
from datetime import datetime

RADIUS = 2  # Umkreis in km
FUEL_TYPE = "E5"  # Spritsorte

URL = "https://www.clever-tanken.de/tankstelle_liste"

FUEL_TYPES = {"diesel": 3, "super e5": 7, "super e10": 5, "super plus": 6}


def convert_type(fuel_type):
    if isinstance(fuel_type, int):
        return fuel_type
    for name, value in FUEL_TYPES.items():
        if fuel_type.casefold() in (name, *name.split()):
            return value
    raise ValueError(f"Unknown type: {fuel_type!r}")


def get_prices(zip_location, radius, fuel_type):
    query = dict(
        ort=zip_location, r=radius, spritsorte=convert_type(fuel_type))
    response = requests.get(URL, query)
    response.raise_for_status()
    return iter_results(response.text)


def iter_results(markup):
    soup = bs4.BeautifulSoup(markup, "html.parser")
    for result in soup.find_all(class_="list-card-container"):
        price = result.find(class_="price").text.strip()
        fuel_location = ", ".join(
            result.find(class_=f"fuel-station-location-{typ}").text.strip()
            for typ in ("name", "street", "city"))
        yield price, fuel_location


def get_header(fuel_type):
    now = datetime.now()
    text = f"Spritpreise ({fuel_type}) am {now:%d.%m.%Y} um {now:%H:%M} Uhr"
    divider = "-" * len(text)
    return f"{text}\n{divider}\n"


def get_zip_code():
    location.start_updates()
    time.sleep(1)
    coord = location.get_location()
    location.stop_updates()
    location_result = location.reverse_geocode(coord)
    return (location_result[0]['ZIP'])


def main():
    zip_location = get_zip_code()
    print(get_header(FUEL_TYPE))
    results = get_prices(zip_location, RADIUS, FUEL_TYPE)
    for price, fuel_location in results:
        print(f"{fuel_location} ({price} €)")


if __name__ == "__main__":
    main()

Antworten