Spritpreise

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

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

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: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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: 23
Registriert: Mittwoch 24. Januar 2018, 20:49
Wohnort: Köln

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()

Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Statt die Konstante für den Ort komplett raus zu werfen, hier mit Konstante auf die zurückgefallen wird, wenn das `location`-Modul nicht importiert werden kann.

Code: Alles auswählen

#!/usr/bin/env python3
import time
from datetime import datetime

import bs4
import requests

try:
    import location  # iOS Pythonista Modul
except ModuleNotFoundError:
    location = None

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 get_zip_code():
    if location is None:
        return LOCATION

    location.start_updates()
    time.sleep(1)
    coord = location.get_location()
    location.stop_updates()
    return location.reverse_geocode(coord)[0]["ZIP"]


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 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 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_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 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()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
cheers
User
Beiträge: 18
Registriert: Samstag 31. Juli 2021, 08:53
Wohnort: Deutschland

hey, ich stöbere hier gerade ein wenig im forum rum, sehr cooles tool :) das macht lust auf mehr -->python :D
:arrow: Viele Grüße und allen eine gute Zeit! :)
Antworten