Seite 1 von 1

Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 13:26
von Makusm
Moin Moin,

bin jetzt seit knapp vier Wochen dabei Python zu lernen...hab mich jetzt seit letzter Woche an mein erstes Eigenes Projekt gesetzt...
Soweit funktioniert auch alles, doch bekomme ich mal nach der 3 mal nach der "x"ten Listenabfrage einen "find_Item_price = soup.find_all(attrs={"market_table_value normal_price"})[0].find("span").text
IndexError: list index out of range" Fehler....
mag mir wer helfen? youtube und Internet habe ich bereits durchsucht.... =(


import requests
import pandas as pd
import time
from bs4 import BeautifulSoup
from math import pi

### Excel Daten abrufen:
file = pd.read_excel("Steam-Market.xlsx")
names_list = (file["Item"].values.tolist())
new_list= [str(s).replace(" ","+")for s in names_list]


### Item Name
def item_name(parameter):
URLname = "https://steamcommunity.com/market/searc ... =252490&q="+ (parameter)
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"}
page = requests.get(URLname, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")
find_item_name = soup.find_all(attrs={"market_listing_item_name_block"})[0].find("span").text
return find_item_name

#item_name(parameter)

### Item market site
def item_price(parameter):
URLitem = "https://steamcommunity.com/market/searc ... =252490&q="+ (parameter)
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"}
page = requests.get(URLitem, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")

### Item Price finden
find_Item_price = soup.find_all(attrs={"market_table_value normal_price"})[0].find("span").text
find_Item_price = find_Item_price.strip("USD $ ")
### Item Price to float USD
find_Item_price = float(find_Item_price)
#print(find_Item_price,"$")
return find_Item_price
#item_price()


### US $ in € umwandeln
def convert(parameter):
URL_EUR_Dollar = "https://www.google.com/search?q=1+euro+ ... e&ie=UTF-8"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"}
page = requests.get(URL_EUR_Dollar, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")

find_EUR_Dollar = soup.find_all(attrs={"DFlfde SwHCTb"})[0].get("data-value")
find_EUR_Dollar = float(find_EUR_Dollar)
find_EUR_Dollar = (find_EUR_Dollar)
### Item von USD in Euro umrechnen
find_Item_price = item_price(parameter)
Price = (find_Item_price / find_EUR_Dollar)
Price = float(Price)
Price = round(Price,2)
#print(Price,"€")
return Price


for x in new_list:

#print(x)
Price = convert(x)
find_item_name = item_name(x)
print(find_item_name, Price,"€")


############
Ich habe eine Liste mit Steam Market Skins, die Namen der Items ergänze ich an eine URL um dann den Preis zu ermitteln...anschließend Dollar in EUR umrechnen und print().

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 13:53
von sparrow
Wenn man eine URL abruft, dann muss man damit rechnen, dass der Inhalt nicht der ist, den man erwartet. Und dem scheint hier zu sein.
Also musst du schauen, was denn als Ergebnis von requests zurück kommt, wenn es zu dem Fehler kommt. Seiten schützen sich im Zweifelsfall auch vor ungewollten Zugriffen.

Edit: Und Code bitte in Code-Blöcke. Die erscheinen wenn du im "vollständigen Editor" den </>-Knopf drückst. Dazwischen gehört dann dein Code.

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 14:21
von Jankie
Mit dem Code hier komm ich an den Preis:

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup

HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}
URL = "https://steamcommunity.com/market/search?category_252490_itemclass[]=any&appid=252490&q=Wood"


def get_item_price(url):          
    page = requests.get(url, headers=HEADERS)
    soup = BeautifulSoup(page.content, "html.parser")
    price = soup.find('span',{'class':'market_table_value normal_price'}).find('span',{'class':'normal_price'}).get_text()
    return price


print(get_item_price(URL))

#edit:

Hab mal bisschen rumprobiert, bei mir Funktioniert das alles soweit.

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup

HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}
STEAM_URL = "https://steamcommunity.com/market/search?category_252490_itemclass[]=any&appid=252490&q="
EURO_URL = "https://www.google.com/search?q=dollar+kurs&ie=utf-8&oe=utf-8"



def get_soup(url):
    page = requests.get(url, headers=HEADERS)
    return BeautifulSoup(page.content, "html.parser")

def get_item_price(url):          
    soup = get_soup(url)
    price = float(soup.find('span',{'class':'market_table_value normal_price'}).find('span',{'class':'normal_price'}).get_text().replace("$", "").replace("USD", ""))
    return price

def get_current_dollar_course(url):          
    soup = get_soup(url)
    course = float(soup.find('span',{'class':'DFlfde SwHCTb'}).get_text().replace(".", "").replace(",","."))
    return course


def calculate_price(item):
    url = f"{STEAM_URL}{item}"
    return get_item_price(url) * get_current_dollar_course(EURO_URL)


def main():
    items = ["Wood", "Cloth", "Glacial Visage Large Box"]
    for item in items:
        print(f"{item}: {round(calculate_price(item),2)} €")

if __name__ == "__main__":
    main()

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 15:17
von Makusm
Also wenn ich deinen unteren Code so benutze bekomme ich Fehlermeldungen AttributeError: 'NoneType' object has no attribute 'find'

beim Oberen "price = soup.find('span',{'class':'market_table_value normal_price'}).find('span',{'class':'normal_price'}).get_text()
AttributeError: 'NoneType' object has no attribute 'find'"

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 15:30
von Jankie
Dann liegt es daran, dass das Item so wahrscheinlich gar nicht existiert (wie hier z.B.). Schreib mal bitte deine Itemliste hier rein.

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 15:50
von Makusm
Jankie hat geschrieben: Dienstag 19. Januar 2021, 15:30 Dann liegt es daran, dass das Item so wahrscheinlich gar nicht existiert (wie hier z.B.). Schreib mal bitte deine Itemliste hier rein.
Black Bandana
Bombing Chest Plate
Bombing Facemask
Bombing Helmet
Bombing Hoodie
Bombing Kilt
Bombing Pants
Bombing Roadsign Vest
Clan Leader Mask
Dead Man Crossbow
Egiptu Garage Door
Eye Scream Door
Forsaken Era Chest Plate
Forsaken Era Mask
Freedom Sleeping Bag
Frost Hammer
Glacial Visage Small Box
Hunting Hatchet
Hunting Pick Axe
Large Fireworks Pack
No Mercy AK47
No Mercy Bolt Rifle
No Mercy LMG
No Mercy SAR
No Mercy SMG
Oil Rig Double Door
Pitstop Bag
Rocket Factory Crew Hoodie
Salvaged APC Door
Small Fireworks Pack
Snowboy
Tribal Revolver
Trust In Rust 3 Box
Victorian Furnace
Volcano Furnace
Winter Hoodie
Winter Pants
Wood Sleeping Bag


#####
Bis auf Eye Scream Door, Freedom Sleeping Bag, No Mercy LMG und Volcano Furnace sind alle im markt enthalten

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 15:57
von Jankie
Dann musst du das Programm so umschreiben, dass wenn keine Ergebnisse gefunden werden der Fehler abgefangen wird und entsprechend behandelt wird (Stichwort: Exceptionhandling)

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 16:04
von Makusm
Jankie hat geschrieben: Dienstag 19. Januar 2021, 15:57 Dann musst du das Programm so umschreiben, dass wenn keine Ergebnisse gefunden werden der Fehler abgefangen wird und entsprechend behandelt wird (Stichwort: Exceptionhandling)
Ich hab die Items jetzt mal aus der Liste rausgenommen....bekomme leider den selben fehler....also liegt es nicht an den items

Re: Erstes Programm mit random Aussetzern

Verfasst: Dienstag 19. Januar 2021, 19:12
von __blackjack__
@Makusm: `time` und `pi` aus dem `math`-Modul werden importiert, aber nirgends verwendet.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

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

Funktions- und Methodennamen beschreiben die Tätigkeit, damit man weiss was die machen und damit man sie besser von eher passiven Werten unterscheiden kann. `item_name` und `item_price` sind keine Tätigkeiten. Dafür werden die Werte in den Funktionen dann mit Namen wie `find_item_name` und `find_item_price` versehen, was sehr verwirrend ist.

`file` ist als Name irreführend wenn da gar kein Dateiobjekt dran gebunden wird.

Grunddatentypen haben nichts in Namen verloren. Den Typen ändert man gar nicht so selten mal während der Programmentwicklung und dann muss man überall im Programm die betroffenen Namen ändern, oder man hat falsche, irreführende Namen im Quelltext.

`new_list` und `x` sind zu nichtssagend. `new_list` ist auch gar nicht nötig. Man kann über `pandas.Series`-Objekte iterieren und muss das auch nicht an einen Namen binden.

Das Ersetzen von Leerzeichen durch "+" in den Eingabedaten geschieht an der falschen Stelle. Und das kann man sich auch sparen wenn man das `requests` überlässt die Daten passend für die URL aufzubereiten.

`item_name()` und `item_price()` teilen sich zu viel Code als dass das zwei verschiedene Funktionen sein sollten. Zumal beide die gleichen Daten vom Webserver abfragen und parsen. Die Arbeit sollte auch nur einmal passieren. Und das ist vielleicht auch ein Grund warum der Webseitenbetreiber Dich noch weniger mag.

`page` ist ein unpassender Name für ein `Response`-Objekt.

Nach der Abfrage sollte man prüfen ob man überhaupt eine Antwort bekommen hat die keine Fehlermeldung ist.

`find_all()` ist die falsche Methode wenn man nur nach dem ersten Vorkommen von etwas sucht.

``find_Item_price.strip("USD $ ")`` ist mindestens mal irreführend und enthält zwei Leerzeichen zu viel. Ich würde da mit ”slicing” arbeiten statt `strip()`.

Funktionsargumente überall einfach nur `parameter` zu nennen ist wenig hilfreich.

Die CSS-Klassennamen bei der Google-Anfrage sind eher fragil, weil das ja nicht die ”echten” Klassennamen sind, sondern welche die ”minified” sind. Das heisst auch wenn der tatsächliche Name sicht nicht ändert, kann sich dieser verkürzte Name bei Änderungen an der Google-Suchseite trotzdem verändern.

`float()` mit `Price` aufzurufen ist sinnfrei, denn das ist bereits eine Gleitkommazahl. Und das `round()` gehört da eher auch nicht rein, das ist was für die Anzeige(formatierung).

Ausserdem ist es vielleicht etwas übertrieben für jeden Gegenstand von Steam direkt nacheinander den Dollarkurs abzufragen. Das kann man auch einfach einmal am Anfang machen.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
import pandas as pd
import requests
from bs4 import BeautifulSoup

APP_ID = "252490"
HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
        " AppleWebKit/537.36 (KHTML, like Gecko)"
        " Chrome/87.0.4280.141 Safari/537.36"
    )
}
STEAM_MARKET_SEARCH_URL = "https://steamcommunity.com/market/search"
GOOGLE_SEARCH_URL = "https://www.google.com/search?q=1+euro+in+dollar"


def get_item_data(search_term):
    response = requests.get(
        STEAM_MARKET_SEARCH_URL,
        params={
            "appid": APP_ID,
            f"category_{APP_ID}_itemclass[]": "any",
            "q": search_term,
        },
        headers=HEADERS,
    )
    response.raise_for_status()
    soup = BeautifulSoup(response.content, "html.parser")
    result_node = soup.find(id="result_0")
    price_text = result_node.find("span", {"data-price": True}).text.strip()
    if not price_text.startswith("$") and price_text.endswith("USD"):
        raise ValueError(f"unexpected currency in {price_text!r}")

    return (
        result_node.find(id="result_0_name").text.strip(),
        float(price_text[1:-3]),
    )


def get_usd_to_eur_factor():
    response = requests.get(GOOGLE_SEARCH_URL, headers=HEADERS)
    response.raise_for_status()
    return 1 / float(
        BeautifulSoup(response.content, "html.parser")
        .find("span", "DFlfde SwHCTb")
        .get("data-value")
    )


def main():
    usd_to_eur_factor = get_usd_to_eur_factor()
    for search_term in pd.read_excel("Steam-Market.xlsx")["Item"]:
        name, price = get_item_data(search_term)
        print(f"{name} {price * usd_to_eur_factor:.2f} €")


if __name__ == "__main__":
    main()