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