'for in'-Zeile als Variable schreiben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
seemarc
User
Beiträge: 10
Registriert: Donnerstag 26. Dezember 2019, 18:52

Ich muss um die Ausgabe weiter bearbeiten zu können folgende Zeile in eine Variable schreiben:

Code: Alles auswählen

for link in link_list:
    print ("https://www.testlink.de/"+(link_list['href']))
Dazu muss die Zeile jedoch umgeschrieben werden, aber ich habe jetzt alles was mir eingefallen funktionierte nicht. Der Grund warum das Ganze so geschrieben ist, ist das ich keine andere Möglichkeit gefunden habe die "href="-Elemente aus der "class": news-morelink zu bekommen. Wäre schön wenn mir wer zeitnah helfen könnte.
LG

Hier nochmal das ganze Script:
'

Code: Alles auswählen

##IMPORT
import requests
from bs4 import BeautifulSoup
#
#
##VARIABLES
URL = 'https://testurl.de/beispielseite'

headers = {"My-User-Agent-placeholder"'}

page = requests.get(URL, headers=headers)

soup = BeautifulSoup(page.content, 'html.parser')

link_list = [div.a for div in soup.findAll ('div', attrs={'class' : 'news-morelink'})] 

##
#
#
##SCRIPT
for link in link_list:
    print ("https://testurl.de.de/"+(link_list['href']))
'
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@seemarc: Diese ``for``-Schleife ist so nicht sinnvoll. Du gehst über jedes Element in `link_list` und benutzt das (`link`) *in* der Schleife gar nicht, sondern versuchst auf `link_list` was auch tatsächlich eine Liste ist, mit einer Zeichenkette zuzugreifen, was schlicht nicht geht, denn als Index bei Listen kann man nur ganze Zahlen verwenden. An der Stelle willst Du wahrscheinlich eigentlich die Schleifenlaufvariable `link` verwenden, denn die Elemente stehen ja für <a>-Tags und die haben ein 'href'-Attribut auf das man so zugreifen kann.

Edit: `page` ist ein irreführender Name weil die Seite nur ein Teil der Antwort vom Server ist. Statt `findAll()` sollte man `find_all()` verwenden. Die unkonventionell benannten Methodennamen werden irgendwann bei einem Update von BeautifulSoup verschwinden. Das `class`-Attribut wird speziell behandelt, da kann man bei `find_all()` & Co einfach den Klassennamen als zweites Argument angeben und muss da kein Wörterbuch für anlegen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Wo ist das Problem? Du weißt schon, wie man Listen z.B. mit List-Comprehension erzeugt. Das mußt Du doch nur auf Deine URLs anwenden.

Deine Kommentare sind übrigens wenig hilfreich. Dass ganz am Anfang Importe stehen, sieht man am ›import‹. Das was Du als VARIABLES beschreibst, sind zum einen Konstanten zum anderen nicht vom SCRIPT zu unterscheiden, weil da ja auch schon weitere Funktionen aufgerufen werden. Alles was da SCRIPT heißt und auch der Teil davor gehört eigentlich in eine Funktion. Variablennamen sollten nicht den Typ im Namen haben, denn der könnte sich leicht ändern, z.B. könnte man ohne weiteres aus der link_liste einen Generator machen. ›findAll‹ sollte man nicht mehr verwenden, weil es nicht der Namenskonvention entspricht. Dafür gibt es nun ›find_all‹. In der letzten Zeile versuchst Du auch auf die Liste link_list mit einem String zugreifen, was nicht funktionieren kann. `link` wird dagegen gar nicht verwendet.

URLs setzt man mit urllib.parse.urljoin zusammen.

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

URL = 'https://testurl.de/beispielseite.html'

def main():
    headers = {"My-User-Agent-placeholder"}
    page = requests.get(URL, headers=headers)
    soup = BeautifulSoup(page.content, 'html.parser')
    links = [div.a for div in soup.find_all('div', attrs={'class' : 'news-morelink'})] 

    for link in link_list:
        print(urljoin(URL, link['href']))

if __name__ == '__main__':
    main()
seemarc
User
Beiträge: 10
Registriert: Donnerstag 26. Dezember 2019, 18:52

@sirius3 @__blackjack__
Erstmal danke euch beiden für die schnelle Antwort. Das es statt "findAll" auch "find_all" gibt wusste ich nicht. Hab es entsprechend geändert.

@__blackjack__
"page" werde ich dann ändern dankschön ;)
@sirius3
Manchmal sieht man den Wald vor lauter Bäumen nicht. Vielen Dank :D
seemarc
User
Beiträge: 10
Registriert: Donnerstag 26. Dezember 2019, 18:52

Weitere Frage wenn ich "main()" (siehe Kommentar @sirius3) nun nochmal als zweite (gleiche) Prozedur mit beispielsweise dem Namen "test()" definiere, und dann:

Code: Alles auswählen

if main() == test():
      tueEtwas
      else:
            tueEtwasAnderes
durchlaufen lasse, wird dann der Output (also die URLs) oder die Prozedur miteinander verglichen?
Benutzeravatar
snafu
User
Beiträge: 6867
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Es wird natürlich die Rückgabe verglichen, da du die Funktion aufrufst. Wenn du das eigentliche Funktionsobjekt prüfen willst, dann musst du die Klammern auf beiden Seiten weglassen.

Angemerkt sei, dass man letzteres nur tun sollte, wenn man sehr gute Gründe dafür hat. Eigentlich braucht man das fast nie. Funktionsobjekte werden höchstens mal herumgereicht, wenn man sie als Callbacks verwendet. Will man hingegen eine Art Typprüfung vornehmen, dann nutzt man dafür Klassen-Exemplare und die isinstance()-Funktion.
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei man da vielleicht dann auch gleich dazu sagen sollte das man auch für eine Typprüfung mit `isinstance()` einen guten Grund haben sollte, denn Typprüfung ist in objektorientierten Programmiersprachen eine „code smell“. Das ist in wenigen Fällen sinnvoll, aber in der Regel ein Hinweis auf ein Problem beim Entwurf.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
seemarc
User
Beiträge: 10
Registriert: Donnerstag 26. Dezember 2019, 18:52

Alles klar vielen Dank.
Antworten