BeautifulSoup optgroup in Dictionary

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
schlake042
User
Beiträge: 7
Registriert: Dienstag 19. Februar 2019, 18:30

Hey Freunde,
ich spiele gerade ein wenig mit BeautifulSoup rum und hänge grad an folgender Stelle.
Ich bin bisher so weit, dass ich eine Liste aus folgenden Elemente habe. (Liste ist untereinander ausgegeben)
Nun würde ich gerne ein Dictionary für jede Position erstellen. Sozusagen als Überbegriff Torwart (Key) und die jeweiligen Spieler als (Value).
Da sich die Anzahl der Spieler, also der Zeilen hier pro Mannschaft verändert, kann ich nicht sagen, Index von 1-4 ist immer Torwart etc.
Jetzt hänge ich hier schon ewig dran und versuche irgendwie eine IF-Funktion zusammenzubasteln, um sozusagen immer von "optgroup" bis "optgroup" zu nehmen und alles dazwischen
in eine neue Liste zu packen. Aber irgendwie krieg ich es nicht hin.

Hat wer von euch eventuell einen Tipp für mich oder eine Hilfestellung? Vielen Dank !

Liebe Grüße
N


<optgroup label="Torwart">
<option value="17259">(1) Manuel Neuer</option>
<option value="40680">(26) Sven Ulreich</option>
<option value="336307">(36) Christian Früchtl</option>
<option value="317444">(39) Ron-Thorben Hoffmann</option>
</optgroup>
<optgroup label="Abwehr">
<option value="161056">(32) Joshua Kimmich</option>
<option value="59016">(27) David Alaba</option>
<option value="166601">(4) Niklas Süle</option>
<option value="39728">(5) Mats Hummels</option>
<option value="26485">(17) Jérôme Boateng</option>
<option value="33947">(13) Rafinha</option>
</optgroup>
<optgroup label="Mittelfeld">
<option value="88103">(11) James Rodríguez</option>
<option value="60444">(6) Thiago</option>
<option value="190393">(24) Corentin Tolisso</option>
<option value="153084">(18) Leon Goretzka</option>
<option value="44017">(8) Javi Martínez</option>
<option value="258027">(35) Renato Sanches</option>
<option value="379980">(37) Meritan Shabani</option>
</optgroup>
<optgroup label="Sturm">
<option value="38253">(9) Robert Lewandowski</option>
<option value="243714">(29) Kingsley Coman</option>
<option value="58358">(25) Thomas Müller</option>
<option value="159471">(22) Serge Gnabry</option>
<option value="424204">(19) Alphonso Davies</option>
<option value="4360">(10) Arjen Robben</option>
<option value="22068">(7) Franck Ribéry</option>
<option value="297583">(20) Woo-yeong Jeong</option>
</optgroup>
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@schlake042: Was genau hast Du denn in einer Liste? Etwa Zeichenketten mit den Zeilen die Du da zeigst? Solltest Du nicht haben wenn Du BeautifulSoup verwendest, denn dann solltest Du eine Liste mit <optgroup>-Elementen haben. Und die haben dann ja trivialerweise die Möglichkeit alle <option>-Elemente von jedem dieser Elemente abzufragen. Und da stehen dann die Informationen drin, die Du für den Wert zu dem Schlüssel (label-Attributwert vom <optgroup>) haben möchtest.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
schlake042
User
Beiträge: 7
Registriert: Dienstag 19. Februar 2019, 18:30

Hi blackjack,

mein Code bis dahin ist dieser hier:

page = "https://www.transfermarkt.de/fc-bayern- ... on_id/2018"
tree = requests.get(page, headers=headers)
soup = BeautifulSoup(tree.content, 'html.parser')

# Richtige Daten raussuchen
kader = soup.select("optgroup")

Wenn ich jetzt die Variabel "kader" ausgebe, kommt der oben gezeigte Code.
Bin ich gerade auf dem Holzweg? Wie rufe ich denn explizit die Label-Attribute auf?
Vielen Dank!

Liebe Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@schlake042: Dann solltest Du als erstes mal verstehen was Du da in der Liste hast. Die Ausgabe sieht ja auch ein klein bisschen anders aus als das was Du zeigst:

Code: Alles auswählen

In [11]: soup('optgroup')
Out[11]: 
[<optgroup label="Torwart">
 <option value="17259">(1) Manuel Neuer</option>
 <option value="40680">(26) Sven Ulreich</option>
 <option value="336307">(36) Christian Früchtl</option>
 <option value="317444">(39) Ron-Thorben Hoffmann</option>
 </optgroup>, <optgroup label="Abwehr">
 <option value="161056">(32) Joshua Kimmich</option>
 <option value="59016">(27) David Alaba</option>
 <option value="166601">(4) Niklas Süle</option>
 <option value="39728">(5) Mats Hummels</option>
 <option value="26485">(17) Jérôme Boateng</option>
 <option value="33947">(13) Rafinha</option>
 </optgroup>, <optgroup label="Mittelfeld">
 <option value="88103">(11) James Rodríguez</option>
 <option value="60444">(6) Thiago</option>
 <option value="190393">(24) Corentin Tolisso</option>
 <option value="153084">(18) Leon Goretzka</option>
 <option value="44017">(8) Javi Martínez</option>
 <option value="258027">(35) Renato Sanches</option>
 <option value="379980">(37) Meritan Shabani</option>
 </optgroup>, <optgroup label="Sturm">
 <option value="38253">(9) Robert Lewandowski</option>
 <option value="243714">(29) Kingsley Coman</option>
 <option value="58358">(25) Thomas Müller</option>
 <option value="159471">(22) Serge Gnabry</option>
 <option value="424204">(19) Alphonso Davies</option>
 <option value="4360">(10) Arjen Robben</option>
 <option value="22068">(7) Franck Ribéry</option>
 <option value="297583">(20) Woo-yeong Jeong</option>
 </optgroup>]
Und das sind keine Zeilen sondern vier Objekte die jeweils ein <optgroup> repräsentieren:

Code: Alles auswählen

In [17]: type(kader[0])
Out[17]: bs4.element.Tag

In [18]: kader[0].name
Out[18]: 'optgroup'

In [19]: kader[0]
Out[19]: 
<optgroup label="Torwart">
<option value="17259">(1) Manuel Neuer</option>
<option value="40680">(26) Sven Ulreich</option>
<option value="336307">(36) Christian Früchtl</option>
<option value="317444">(39) Ron-Thorben Hoffmann</option>
</optgroup>
An die Attribute von Elementen kommt man mit der `get()`-Methode:

Code: Alles auswählen

In [20]: kader[0].get('label')
Out[20]: 'Torwart'
An die enthaltenen `Tag`-Objekte mit den <options>-Werten kommt man genau so wie man an die <optgroup>-Tags gekommen ist:

Code: Alles auswählen

In [21]: kader[0]('option')
Out[21]: 
[<option value="17259">(1) Manuel Neuer</option>,
 <option value="40680">(26) Sven Ulreich</option>,
 <option value="336307">(36) Christian Früchtl</option>,
 <option value="317444">(39) Ron-Thorben Hoffmann</option>]
Und das ganze als Liste mit Tupeln aus Position und Spielernamen:

Code: Alles auswählen

In [22]: [(group.get('label'), [player.text for player in group('option')]) for group in soup('optgroup')]
Out[22]: 
[('Torwart',
  ['(1) Manuel Neuer',
   '(26) Sven Ulreich',
   '(36) Christian Früchtl',
   '(39) Ron-Thorben Hoffmann']),
 ('Abwehr',
  ['(32) Joshua Kimmich',
   '(27) David Alaba',
   '(4) Niklas Süle',
   '(5) Mats Hummels',
   '(17) Jérôme Boateng',
   '(13) Rafinha']),
 ('Mittelfeld',
  ['(11) James Rodríguez',
   '(6) Thiago',
   '(24) Corentin Tolisso',
   '(18) Leon Goretzka',
   '(8) Javi Martínez',
   '(35) Renato Sanches',
   '(37) Meritan Shabani']),
 ('Sturm',
  ['(9) Robert Lewandowski',
   '(29) Kingsley Coman',
   '(25) Thomas Müller',
   '(22) Serge Gnabry',
   '(19) Alphonso Davies',
   '(10) Arjen Robben',
   '(7) Franck Ribéry',
   '(20) Woo-yeong Jeong'])]
Wobei der erste Schritt für meinen Geschmack nicht robust genug ist, weil es ja mehr als ein <select> auf einer Seite geben kann, und man sich ja schon ganz gerne nur die Daten rausfischen möchte die dann auch tatsächlich die Mannschaft enthalten. Das umschliessende <select> hat ja eine ID.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
schlake042
User
Beiträge: 7
Registriert: Dienstag 19. Februar 2019, 18:30

Hallo blackjack,

sorry, dass ich jetzt erst antworte. Oh man, ich fühle mich so, als ob ich am Leben vorbei laufe :D
Ich bedanke mich trotzdem. Du hast mir ziemlich geholfen! Demnächst gehe ich anders an solche Probleme ran.

Vielen Dank !
Antworten