Seite 1 von 1

Zahlenformat ändern

Verfasst: Samstag 15. Januar 2022, 15:23
von iFloFIFA
Hallo,
ich hab das Problem das mein "Web Scrapper" mir die Zahl in Google Sheet so ausgibt '12500. Durch das ' hab ich das Problem, dass die bedingte Formatierung bei jedem automatisierten Scrap nicht mehr funktioniert und ich erst manuel das Zahlenformat wieder ändern muss.

Gibt es in diesem Code die Möglichkeit das ' zu entfernen?
Ich bedanke mich schonmal ganz herzlich.

Code: Alles auswählen

# Call the Sheets API
    sheet = service.spreadsheets()
    result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID,
                                range=SAMPLE_RANGE_NAME).execute()
    values = result.get('values', [])
    print('values: ', values)
    user_agent = {'User-agent': 'Mozilla/5.0'}
    prices=[]
    proxy_host = "proxy.zyte.com"
    proxy_port = "8011"
    proxy_auth = "db4255942ad341c78efcfef838239084:" # Make sure to include ':' at the end
    proxies = {"https": "http://{}@{}:{}/".format(proxy_auth, proxy_host, proxy_port),
               "http": "http://{}@{}:{}/".format(proxy_auth, proxy_host, proxy_port)}
    r=requests.Session()
    r.proxies = proxies
    for i in values:
        if i != []:
            page=None
            try:
                page = r.get('https://www.futbin.com/22/playerPrices?player=' + i[0], verify='zyte-smartproxy-ca.crt')
                print('page response: ', page.reason)
                data=json.loads(page.content)
                print(data)
                psLcPrice = data[i[0]]['prices']['ps']['LCPrice']
                xboxLcPrice = data[i[0]]['prices']['xbox']['LCPrice']
                psMinPrice = data[i[0]]['prices']['ps']['MinPrice']
                psMaxPrice = data[i[0]]['prices']['ps']['MaxPrice']
                xboxMinPrice = data[i[0]]['prices']['xbox']['MinPrice']
                xboxMaxPrice = data[i[0]]['prices']['xbox']['MaxPrice']
                prices.append([psLcPrice.replace(',', ''), xboxLcPrice.replace(',', ''), psMinPrice.replace(',', ''), psMaxPrice.replace(',', ''), xboxMinPrice.replace(',', ''), xboxMaxPrice.replace(',', '')])
            except:
                print('page error: ')
                prices.append('None')
        else:
            prices.append([])
    print('Successfully got all Prices!')
    modified = sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, valueInputOption="RAW" ,range="Python!E3", body={'values':prices}).execute()

getPlayerPrices()
Ursprünglich wurde die Zahl mit '12,500 ausgegeben. Das , konnte bereits entfernt werden, aber mit dem ' bin ich überfragt. Vielen Dank für die Hilfe

Re: Zahlenformat ändern

Verfasst: Samstag 15. Januar 2022, 15:54
von rogerb
@iFloFIFA,

damit google spreadsheets das als Zahl erkennt, must du es wahrscheinlich auch als float übergeben. Aktuell scheint 12,500 eine Zeichenkette zu sein, die wie eine Zahl aussieht.
Also auch das replace ist eigentlich keine gute Lösung. Besser wäre es gleich in float zu wandeln.

Re: Zahlenformat ändern

Verfasst: Samstag 15. Januar 2022, 15:58
von __deets__
Es gibt wirklich viele Tutorials zum Thema String-Verarbeitung in Python. ZB im offiziellen: https://docs.python.org/3/tutorial/intr ... ml#strings

Das solltest du mal durcharbeiten, dann stellt sich hoffentlich der gewuenschte Aha-Effekt ein.

Eine Anmerkung zur Benamung: der Akt des "auskratzens" ist scraping. Also hast du einen Web-Scraper. Scrapping ist der Vorgang des Verschrottens. Also etwas sehr anderes.

Re: Zahlenformat ändern

Verfasst: Samstag 15. Januar 2022, 16:11
von iFloFIFA
rogerb hat geschrieben: Samstag 15. Januar 2022, 15:54 @iFloFIFA,

damit google spreadsheets das als Zahl erkennt, must du es wahrscheinlich auch als float übergeben. Aktuell scheint 12,500 eine Zeichenkette zu sein, die wie eine Zahl aussieht.
Also auch das replace ist eigentlich keine gute Lösung. Besser wäre es gleich in float zu wandeln.
Danke für den Hinweis. Ich hab den Code schreiben lassen und dachte, dass es vielleicht nur irgendeine Kleinigkeit wäre, das zu ändern.
Dann werde ich mich mal mit dem Thema "float" beschäftigen.

Re: Zahlenformat ändern

Verfasst: Samstag 15. Januar 2022, 20:15
von __blackjack__
@iFloFIFA: Anmerkungen zum Quelltext: `user_agent` wird definiert aber nicht verwendet. Entweder fügt den Wert dafür bei dem `Session`-Objekt hinzu oder lässt entfernt die überflüssige Definition.

Die `proxy_*`-Variablen sehen sehr nach Konstanten aus.

`proxies` als Zwischenergebnis könnte man sich sparen wenn man das Wörterbuch erst nach dem `Session`-Objekt erstellt. Da man das dort dann dem Attribut `proxies` zuweist, geht durch den ”fehlenden” Namen des Zwischenergebnis auch für den Leser überhaupt keine Information verloren.

Statt der `format()`-Methode würde man an der Stelle besser f-Zeichenkettenliterale verwenden.

Einbuchstabige Namen sind selten eine gute Idee. `r` steht für `Session`? Wie soll man denn *darauf* kommen? Und `i` als Schleifenvariable ist eine ganze Zahl. Wenn das keine ganze Zahl ist, dann heisst das verdammt noch mal nicht `i`!

Weil `i` so grottenschlecht als Name ist, weiss ich jetzt nicht wie man das besser benennen sollte, denn aus dem Quelltext geht die tatsächliche *Bedeutung* dieses Wertes nicht wirklich hervor.

Die ``page = None``-Zuweisung macht keinen Sinn die kann einfach weg ohne das sich am Programmablauf etwas ändert.

`page` kein besonders guter Name für ein `Response`-Objekt. Ob das eine ”Seite” ist oder nicht hängt vom Inhalt der Antwort ab, beziehungsweise *ist* das eigentlich nie eine “Seite“ sondern *enthält* höchstens eine Seite.

Das `verify`-Argument möchte man vielleicht auch auf dem `Session`-Objekt setzen, damit man das nicht bei jedem Aufruf angeben muss.

URL-Parameter per Zeichenkettenoperationen zusammen zu basteln ist keine gute Idee. Da muss je nach Inhalt mehr passieren als einfach nur die Zeichenketten zu verbinden und `requests` macht das alles netterweise schon für einen, also sollte man das auch nutzen.

Das gleiche gilt für JSON-Ergebnisse — die muss man nicht selbst deserialisieren, da haben `Response`-Objekte bereits eine Methode für.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Da das Konvertieren von einer Zeichenkette mit einem Dezimalkomma in eine Zahl mehrfach vorkommt, würde man dafür eine Funktion schreiben, statt immer wieder den gleichen Code zu wiederholen. Beziehungsweise könnte man gleich eine Funktion schreiben, die die Werte für eine Konsole komplett ausliest und als Objekt liefert.

So ein nacktes ``except`` ohne konkrete Ausnahme ist eine ganz schlechte Idee. Wenn da irgendwo ein Fehler ist, wird der einfach durch "None" und eine nichtssagende Ausgabe ersetzt und ist damit nur sehr schwer zu finden. ``except`` ohne konkrete Ausnahme(n) kann man eigentlich nur machen wenn man die Ausnaheme wieder auslöst, damit die Information nicht verloren geht, oder komplett mit Traceback irgendwo protokolliert. Das kann man mit `logging` aus der Standardbibliothek machen, oder beispielsweise mit dem externen `loguru`.

Die *Zeichenkette* "None" ist ein komischer Wert. Das ist etwas anderes als das `None`-Objekt. Es ist auch etwas komisch eine Liste mit Listen zu haben und dazwischen dann ab und zu vielleicht eine Zeichenkette "None" statt einer Liste. Das ist unsauber, erschwert die Weiterverarbeitung massiv, und ich habe den Eindruck das ist hier an der Stelle nicht wirklich weiter gedacht worden, was beispielsweise dann die Google-API macht. Am Ende fällt die dann auch einfach nur mit einer Ausnahme auf die Nase. Oder die interpretiert das als Sequenz von Zellenwerten und man hat dann eine Zeile mit vier Zellen wo in jeder Zelle ein Buchstabe von "None" steht. Wäre das wirklich sinnvoll? So gewollt?

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import logging
import math
from collections import namedtuple
...

LOGGER = logging.getLogger(__name__)

PROXY_HOST = "proxy.zyte.com"
PROXY_PORT = 8011
#
# Make sure to include ':' at the end.
#
PROXY_AUTH = "db4255942ad341c78efcfef838239084:"

...

Price = namedtuple("Price", "lc min max")


def get_price(name_to_value):
    return Price(
        *(
            float(name_to_value[name].replace(",", "."))
            for name in ["LCPrice", "MinPrice", "MaxPrice"]
        )
    )

...

def some_function():
    ...

    sheet = service.spreadsheets()
    values = (
        sheet.values()
        .get(spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE_NAME)
        .execute()
    ).get("values", [])
    LOGGER.info("values: %s", values)

    session = requests.Session()
    session.proxies = {
        "https": f"http://{PROXY_AUTH}@{PROXY_HOST}:{PROXY_PORT}/",
        "http": f"http://{PROXY_AUTH}@{PROXY_HOST}:{PROXY_PORT}/",
    }
    session.verify = "zyte-smartproxy-ca.crt"
    prices = []
    #
    # TODO `items` and `item` need better names.
    #
    for items in values:
        if items:
            item = items[0]
            try:
                response = session.get(
                    "https://www.futbin.com/22/playerPrices",
                    params={"player": item},
                )
                LOGGER.info("response reason: %s", response.reason)
                data = response.json()
                LOGGER.info("%r", data)
                prices_data = data[item]["prices"]
                ps_price = get_price(prices_data["ps"])
                xbox_price = get_price(prices_data["xbox"])
                prices.append(
                    [
                        ps_price.lc,
                        xbox_price.lc,
                        ps_price.min,
                        ps_price.max,
                        xbox_price.min,
                        xbox_price.max,
                    ]
                )
            except:
                LOGGER.exception("response error")
                #
                # TODO Maybe do something different here?
                #
                prices.append([])
        else:
            prices.append([])
    LOGGER.info("Successfully got all Prices!")

    modified = (
        sheet.values()
        .update(
            spreadsheetId=SAMPLE_SPREADSHEET_ID,
            valueInputOption="RAW",
            range="Python!E3",
            body={"values": prices},
        )
        .execute()
    )
    
    ...

Re: Zahlenformat ändern

Verfasst: Sonntag 16. Januar 2022, 01:17
von iFloFIFA
Vielen lieben Dank für deine Antwort. Ich hab mir den Code schreiben lassen, von jemanden auf Fiverr, da ich schlichtweg keine Ahnung von Programmierung/Python habe. Letztendlich wurde durch den Programmierer nicht sauber gearbeitet? Ansich bekomme ich die Daten von der Seite die ich scrape in mein Google Sheet, nur eben wird der Preis z.B. als '12500 ausgegeben, was meine bedingte Formatierung nicht verarbeiten kann.

Werd mich mal mit dem Thema Python beschäftigen und versuchen anhand deines Codes das Ganze zum Laufen zu bringen.
Vielen Dank für deine Mühe :)