Webscraping for-Schleife (mehrere Links)

Code-Stücke können hier veröffentlicht werden.
Antworten
sommares
User
Beiträge: 4
Registriert: Mittwoch 3. Februar 2021, 13:44

Hallo zusammen,

ich bin gerade an einem Webscraping Projekt und versuche innerhalb von Links, die ich mir scrape, weitere Infos auszugeben.

Code: Alles auswählen

import requests
from bs4 import BeautifulSoup

# 1. Stepstone nach Junior Consultant Jobs durchsuchen 

url = 'https://www.stepstone.de/jobs/Junior-Consultant.html'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0)'}

res = requests.get(url, headers=headers)

soup = BeautifulSoup(res.text, 'html.parser')

angebote = soup.select('.job-element__url')

print(len(angebote))

# 2. Innerhalb der Berufe die Anforderungen scrapen

for angebot in angebote:
  print(angebot.get('href'))
  for angebot in angebote:
      print(angebot.get('at-section-text-profile-content'))
Ich lasse mir damit eine Liste von Links ausgeben lassen und versuche innerhalb von jedem Link das Element "at-section-text-profile-content" auszulesen, jedoch erhalte ich immer "none".

Es sollte so aussehen:
<Link/Beruf>
Anforderung 1...
Anforderung 2...


Ich bin um jede Hilfe dankbar!
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sommares: Du liest da Attrbut der <a>-Elemente aus und die haben so ein Attribut nicht. Die haben auch die Anforderungen nicht als Kindelemente. Da ist nur der Link drin. Den Text "at-section-text-profile-content" finde ich in der gesamten Seite nicht.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
sommares
User
Beiträge: 4
Registriert: Mittwoch 3. Februar 2021, 13:44

__blackjack__ hat geschrieben: Mittwoch 3. Februar 2021, 16:52 @sommares: Du liest da Attrbut der <a>-Elemente aus und die haben so ein Attribut nicht. Die haben auch die Anforderungen nicht als Kindelemente. Da ist nur der Link drin. Den Text "at-section-text-profile-content" finde ich in der gesamten Seite nicht.
danke für die Antwort.
ich habe beispielsweise mal den zweiten Link geöffnet der erscheint (https://www.stepstone.de/stellenangebot ... mb_m_0_0_0) und dort unter "Dein Profil" finde ich das Attribut "at-section-text-profile-content".

wie lese ich die div-attribute aus, damit es gefunden wird?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sommares: Wenn die Daten auf einer anderen Webseite sind als das <a>-Element dann muss man sich die Webseite natürlich erst einmal holen. Also selber aktiv vom Server abfragen und parsen und dann *da* drin nach den Daten suchen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Hab das mal versucht umzusetzen, allerdings habe ich kaum Ahnung von HTML, daher denke ich dass meine Methode nicht wirklich robust ist. Da ich auf Klassen mit komischen Bezeichnungen zugreife wie z.B. "sc-jwKygS guXuLZ sc-cmTdod cgayqw". Ist das so üblich beim erstellen von Websiten oder wieso werden solche Bezeichnungen verwendet? Jedenfalls funktioniert das Script soweit. Würde mich aber trotzdem über Verbesserungsvorschläge oder Anmerkungen freuen, von jemandem der von dem ganzen Thema mehr Ahnung hat.

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests

HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}

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

def get_hrefs_from_soup(soup):
    results = soup.find_all('article',{'class':'job-element'})
    return [result.find('a',{'class':'job-element__url job-element__url--shortened-title'}).get('href') for result in results]

def main():
    soup = make_soup("https://www.stepstone.de/jobs/Junior-Consultant.html")
    hrefs_from_results = get_hrefs_from_soup(soup)
    for href in hrefs_from_results:
        soup_from_href =  make_soup(href)
        title = soup_from_href.find('h1',{'class':'listing__job-title at-header-company-jobTitle sc-jAaTju egCVVj'}).get_text().strip()
        company = soup_from_href.find('h1',{'class':'sc-jWBwVP yIdcv'}).get_text().strip()
        location = soup_from_href.find('li',{'class':'at-listing__list-icons_location js-map-offermetadata-link sc-iAyFgw hdLeLh'}).get_text().strip()
        requirements = soup_from_href.find_all('div',{'class':'sc-jwKygS guXuLZ sc-cmTdod cgayqw'})[2].get_text().strip()
        print(f"[Bezeichnung:]\n{title}\n")
        print(f"[Firma:]\n{company}\n")
        print(f"[Ort:]\n{location}\n")
        print(f"[Anforderungen:]\n{requirements}\n\n")


if __name__ == "__main__":
    main()
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Jankie hat geschrieben: Donnerstag 4. Februar 2021, 08:10Da ich auf Klassen mit komischen Bezeichnungen zugreife wie z.B. "sc-jwKygS guXuLZ sc-cmTdod cgayqw". Ist das so üblich beim erstellen von Websiten oder wieso werden solche Bezeichnungen verwendet?
Die sind höchstwahrscheinlich generiert. Das macht man um sicherzustellen dass die Namen global einzigartig sind oder um die Größe von Dateien zu minimieren.

Wie robust dein Scraper ist wenn du von solchen Namen abhängst, hängt davon ab wie die Namen generiert werden. Ich würde erwarten dass du schon ziemlich schnell merken wirst, wenn es nicht robust sein sollte.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Frage ist ob das überhaupt nötig ist, denn da scheinen ja auch semantische Klassen in Klartext vorhanden zu sein. Reichen die zur Identifizierung nicht aus? Am besten auch in Kombination mit etwas gezielterem statt immer die gesamte Seite nach allen Überschriften oder gar Listenelementen zu durchsuchen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
sommares
User
Beiträge: 4
Registriert: Mittwoch 3. Februar 2021, 13:44

Jankie hat geschrieben: Donnerstag 4. Februar 2021, 08:10 Hab das mal versucht umzusetzen, allerdings habe ich kaum Ahnung von HTML, daher denke ich dass meine Methode nicht wirklich robust ist. Da ich auf Klassen mit komischen Bezeichnungen zugreife wie z.B. "sc-jwKygS guXuLZ sc-cmTdod cgayqw". Ist das so üblich beim erstellen von Websiten oder wieso werden solche Bezeichnungen verwendet? Jedenfalls funktioniert das Script soweit. Würde mich aber trotzdem über Verbesserungsvorschläge oder Anmerkungen freuen, von jemandem der von dem ganzen Thema mehr Ahnung hat.

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests

HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}

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

def get_hrefs_from_soup(soup):
    results = soup.find_all('article',{'class':'job-element'})
    return [result.find('a',{'class':'job-element__url job-element__url--shortened-title'}).get('href') for result in results]

def main():
    soup = make_soup("https://www.stepstone.de/jobs/Junior-Consultant.html")
    hrefs_from_results = get_hrefs_from_soup(soup)
    for href in hrefs_from_results:
        soup_from_href =  make_soup(href)
        title = soup_from_href.find('h1',{'class':'listing__job-title at-header-company-jobTitle sc-jAaTju egCVVj'}).get_text().strip()
        company = soup_from_href.find('h1',{'class':'sc-jWBwVP yIdcv'}).get_text().strip()
        location = soup_from_href.find('li',{'class':'at-listing__list-icons_location js-map-offermetadata-link sc-iAyFgw hdLeLh'}).get_text().strip()
        requirements = soup_from_href.find_all('div',{'class':'sc-jwKygS guXuLZ sc-cmTdod cgayqw'})[2].get_text().strip()
        print(f"[Bezeichnung:]\n{title}\n")
        print(f"[Firma:]\n{company}\n")
        print(f"[Ort:]\n{location}\n")
        print(f"[Anforderungen:]\n{requirements}\n\n")


if __name__ == "__main__":
    main()
vielen Dank für dein Skript!
Allerdings erhalte ich die Meldung "AttributeError: 'NoneType' object has no attribute 'get'". Ich habe mal bisschen rumprobiert, kriege den Fehler aber nicht weg...
hättest du noch eine Idee?
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Leider verrätst du nicht, wo die Ausnahme auftritt. Davon hängt ab, was du prüfen musst. Du musst damit rechnen, dass ein Element auf der Seite nicht gefunden wird. Entweder, weil sich die seltsamen Klassennamen geändert haben oder weil eine Fehlerseite angezeigt wird - zum Beispiel weil die Seite die da abrufst Gegenmaßnahmen ergreift. Die wenigsten Seiten mögen und erlauben das automatische Abgreifen ihrer Daten.
Antworten