Seite 1 von 1
BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Mittwoch 11. November 2009, 13:31
von jeff84
Hallo Leute,
ich versuche mit Python und BeautifulSoup eine Tabelle automatisch auszulesen.
Ich bin soweit, dass ich die Tabelle ausgewählt habe, die ich suche:
Code: Alles auswählen
import urllib2
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(urllib2.urlopen(' URL ').read())
tables = soup.findAll("table", { TABEIG })
print tables
Nun suche ich nach einer Möglichkeit statt des letzten print tables die Tabelle in ihren Einzelheiten auszulesen. Allerdings finde ich keine wirkliche Möglichkeit einzelne Teile der Tabelle direkt zu identifizieren, da diese keine id oder Unterscheidungsmerkmale haben. Welche Möglichkeiten habe ich da?
Gruß
EDIT: Der lebarkeit halber URL und TABEIG ersetzt. Im Code weiter unten wieder richtig zu finden...
Verfasst: Mittwoch 11. November 2009, 13:39
von Hyperion
Du müßtest dann eben über die Elemente iterieren (alle <td>s z.B.) und die gewünschten Daten extrahieren.
Verfasst: Mittwoch 11. November 2009, 17:08
von jeff84
Wahrscheinlich ist der Code unsauber wie ein Wildschwein im Wald, aber ich denke ich habe eine Lösung gefunden...
Code: Alles auswählen
import urllib2
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(urllib2.urlopen(' URL ').read())
tables = soup.findAll("table", { TABEIG })
table = tables[1]
#f = open('/home/jochen/sistest', 'w')
#f.write(table.read())
#f.close()
for row in table.findAll('tr')[1:]:
col = row.findAll('td')
Team = row.findAll('a')
try:
col[1]
except:
continue
Platz = col[1].string
Mannschaft = Team[0].string
Spiele = col[3].string
Siege = col[4].string
Unentschieden = col[5].string
Niederlagen = col[6].string
Tore = col[7].string
Tordiff = col[8].string
Punkte = col[9].string
Zeile = (Platz, Mannschaft, Spiele, Siege, Unentschieden, Niederlagen, Tore, Tordiff, Punkte)
print Zeile
Gefällt mir an sich ganz gut. Kann man da noch was verbessern

?
Dann werde ich mich mal daran machen, das irgendwie in ne Datenbank zu bekommen...
EDIT: Der lebarkeit halber URL und TABEIG ersetzt. Im Code weiter unten wieder richtig zu finden...
Verfasst: Mittwoch 11. November 2009, 17:28
von Hyperion
- bei except niemals alle Exceptions abfangen!
- wozu willst Du jedes einzelne Attribut benennen? Du verwendest die Namen ja quasi gar nicht. Wenn doch, würde ich statt eines Tupels ein dict nehmen.
- Zeilenlänge kürzen! PEP8 erlaubt max. 80 Zeichen.
Verfasst: Mittwoch 11. November 2009, 19:21
von HWK
Hyperion hat geschrieben:PEP8 erlaubt max. 80 Zeichen.
79 Zeichen.
MfG
HWK
Verfasst: Mittwoch 11. November 2009, 19:41
von jeff84
Hyperion hat geschrieben:- bei except niemals alle Exceptions abfangen!
In diesem Fall dachte ich, kann nicht viel passieren. Werde vielleicht auch einfach per if bei den col's mit nur einem Element ein continue machen
Hyperion hat geschrieben:
- wozu willst Du jedes einzelne Attribut benennen? Du verwendest die Namen ja quasi gar nicht. Wenn doch, würde ich statt eines Tupels ein dict nehmen.
Die Namen sind vegeben, dass ich das ganze mal sehr sauber dastehen habe um später in ne DB zu übergeben.
Hyperion hat geschrieben:
- Zeilenlänge kürzen! PEP8 erlaubt max. 80 Zeichen.
Wat?

Verfasst: Mittwoch 11. November 2009, 22:14
von Hyperion
jeff84 hat geschrieben:
Hyperion hat geschrieben:
- wozu willst Du jedes einzelne Attribut benennen? Du verwendest die Namen ja quasi gar nicht. Wenn doch, würde ich statt eines Tupels ein dict nehmen.
Die Namen sind vegeben, dass ich das ganze mal sehr sauber dastehen habe um später in ne DB zu übergeben.
Hm... das Einfügen passiert doch meist eh über ein Tupel. Zudem fände ich ein dict dann immer noch übersichtlicher. Zumal man den Code mit einer Liste oder einem dict wesentich kompakter schreiben könnte.
jeff84 hat geschrieben:
Hyperion hat geschrieben:
- Zeilenlänge kürzen! PEP8 erlaubt max. 80 Zeichen.
Wat?

PEP8
@HWK: Ooops

Verfasst: Donnerstag 12. November 2009, 08:12
von jeff84
Hyperion hat geschrieben:
Hm... das Einfügen passiert doch meist eh über ein Tupel. Zudem fände ich ein dict dann immer noch übersichtlicher. Zumal man den Code mit einer Liste oder einem dict wesentich kompakter schreiben könnte.
Ok, dazu hab ich mir noch keine Gedanken gemacht, wie ich das einfüge/eingefügt bekomme... Wollte es halt etwas übersichtlich haben, damit ich gleich weiß, welches Feld was ist, ohne mir das nochmal genauer anschauen zu müssen.
Hyperion hat geschrieben:
PEP8
@HWK: Ooops

Ok, gut zu wissen. Aber wie bekomme ich solche Zeilen, die zu lange sind, möglichst schön gekürzt? Alleine der Link ist doch schon 101 Zeichen lang...
Auf jeden Fall schonmal danke für alle Kritiken. Bin noch am Lernen und da hilft das...
Verfasst: Donnerstag 12. November 2009, 08:37
von cofi
jeff84 hat geschrieben:Ok, gut zu wissen. Aber wie bekomme ich solche Zeilen, die zu lange sind, möglichst schön gekürzt? Alleine der Link ist doch schon 101 Zeichen lang...
Du kannst die Url an einen Namen binden
ob es darueber hinaus noch sinnvoll ist die URL zu zerlegen und dann wieder zusammenzusetzen bezweifel ich, aber alleine durch das auslagern ist dir schon geholfen.
Verfasst: Donnerstag 12. November 2009, 08:46
von jeff84
Gut, hab das Ganze nach euren Tipps weiter angepasst. Die Link-Zeile ist trotzdem noch zu lang. Genauso wie bei den tabeig die style-Zeile...
Code: Alles auswählen
import mechanize
from BeautifulSoup import BeautifulSoup
br = mechanize.Browser()
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2')]
url = 'http://www.sis-handball.de/web/Default.aspx?view=Tabelle&Liga=001510504503503000000000000000000003000'
soup = BeautifulSoup(br.open(url).read())
tabeig = {
"cellpadding" : "0",
"cellspacing" : "0",
"style" : STYLE
}
tables = soup.findAll("table", tabeig)
table = tables[1]
for row in table.findAll('tr')[1:]:
col = row.findAll('td')
Team = row.findAll('a')
try:
col[1]
except IndexError:
continue
Zeile = {
'Platz' : col[1].string,
'Mannschaft' : Team[0].string,
'Spiele' : col[3].string,
'Siege' : col[4].string,
'Unentschieden' : col[5].string,
'Niederlagen' : col[6].string,
'Tore' : col[7].string,
'Tordiff' : col[8].string,
'Punkte' : col[9].string
}
print Zeile
EDIT: Der lebarkeit halber STYLE ersetzt. Im Code weiter unten wieder richtig zu finden...
Verfasst: Donnerstag 12. November 2009, 08:59
von cofi
Code: Alles auswählen
"style" : "font-family:Lucida Sans, Verdana, Arial;color: #272829; "
"font-size: 14px; text-align:center; margin-left: auto; "
"margin-right: auto; width: 95%; margin-top: 5px; "
"margin-bottom: 5px;" }
Verfasst: Donnerstag 12. November 2009, 09:06
von Hyperion
Evtl. könnte man die Zuordnung der Daten noch ein wenig kompakter schreiben:
Code: Alles auswählen
In [1]: keys = ("Platz", "Mannschaft", "Spiele")
In [3]: col = [1, "b", 42]
In [4]: zip(keys, col)
Out[4]: [('Platz', 1), ('Mannschaft', 'b'), ('Spiele', 42)]
In [5]: dict(zip(keys, col))
Out[5]: {'Mannschaft': 'b', 'Platz': 1, 'Spiele': 42}
Da in Deiner col-Liste wohl aber Objekte stehen, bei denen Du auf ein "string"-Attribut zugreifst, müßte man mal gucken, ob das auch per str() Funktion klappt. Zur Not würde man das dann auch mit einer wrapper-Funktion lösen können - wobei sich dann die Frage stellt, ob das noch sinnvoll ist
Noch was zur Codierung: Nach PEP8
team statt Team und zeile statt Zeile.
Wobei man sich dann noch streiten kann, ob man nicht ganz auf Deutsche Bezeichner verzichtet

Verfasst: Donnerstag 12. November 2009, 09:22
von jeff84
Hyperion hat geschrieben:Evtl. könnte man die Zuordnung der Daten noch ein wenig kompakter schreiben:
Code: Alles auswählen
In [1]: keys = ("Platz", "Mannschaft", "Spiele")
In [3]: col = [1, "b", 42]
In [4]: zip(keys, col)
Out[4]: [('Platz', 1), ('Mannschaft', 'b'), ('Spiele', 42)]
In [5]: dict(zip(keys, col))
Out[5]: {'Mannschaft': 'b', 'Platz': 1, 'Spiele': 42}
Da in Deiner col-Liste wohl aber Objekte stehen, bei denen Du auf ein "string"-Attribut zugreifst, müßte man mal gucken, ob das auch per str() Funktion klappt. Zur Not würde man das dann auch mit einer wrapper-Funktion lösen können - wobei sich dann die Frage stellt, ob das noch sinnvoll ist
Noch was zur Codierung: Nach PEP8
team statt Team und zeile statt Zeile.
Wobei man sich dann noch streiten kann, ob man nicht ganz auf Deutsche Bezeichner verzichtet

Das ist ne deutsche Webseite und ich verwende das Ding und ich kann deutsch

. Also werde ich dabei bleiben

.
Das mit der Zuordnung verstehe ist, allerdings ist noch das Problem, dass Mannschaft nicht in col[1] steht, sondern in team[0].
Außerdem hab ich nun mal noch die Strings mit reinen Zahlen in ints umgewandelt, da ich nicht weiß, ob ich das irgendwie noch brauchen kann. Außerdem ist das ganze nicht als was wichtiges produktives gedacht, sondern aus Spaß an der Freude zum Lernen.
Code: Alles auswählen
import mechanize
from BeautifulSoup import BeautifulSoup
br = mechanize.Browser()
br.addheaders = [('User-agent', 'Mozilla/5.0 '
'(X11; U; Linux i686; de; rv:1.9.1.2) '
'Gecko/20090729 Firefox/3.5.2')]
url = 'http://www.sis-handball.de/web/Default.aspx?view=Tabelle&Liga=001510504503503000000000000000000003000'
soup = BeautifulSoup(br.open(url).read())
tabeig = {
"cellpadding" : "0",
"cellspacing" : "0",
"style" : "font-family:Lucida Sans, Verdana, Arial;color: #272829; "
"font-size: 14px; text-align:center; margin-left: auto; "
"margin-right: auto; width: 95%; margin-top: 5px; "
"margin-bottom: 5px;"
}
tables = soup.findAll("table", tabeig)
table = tables[1]
for row in table.findAll('tr')[1:]:
col = row.findAll('td')
team = row.findAll('a')
try:
col[1]
except IndexError:
continue
zeile = {
'Platz' : int(col[1].string),
'Mannschaft' : team[0].string,
'Spiele' : col[3].string,
'Siege' : int(col[4].string),
'Unentschieden' : int(col[5].string),
'Niederlagen' : int(col[6].string),
'Tore' : col[7].string,
'Tordiff' : int(col[8].string),
'Punkte' : col[9].string
}
print zeile
Danke auf jeden Fall für eure Hilfen. Ich freue mich über alle Anregungen...
Verfasst: Donnerstag 12. November 2009, 09:26
von Hyperion
jeff84 hat geschrieben:
Das mit der Zuordnung verstehe ist, allerdings ist noch das Problem, dass Mannschaft nicht in col[1] steht, sondern in team[0].
Na gut, das könnte man ja hinter immer noch ins dict adden! Bei einem dict kommt es ja eben nicht auf die Reihenfolge an

Re: BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Donnerstag 22. März 2012, 02:34
von hans.mueller1206
wenn hier jmd. noch aktiv ist und mir helfen kann eine Tabelle auszulesen soll der jenige sich doch bitte kurz melden! Ich suche eine Möglichkeit ein Plugin zu schreiben und würde gerne die 1. BL Tabelle auslesen, danke sehr!!!
Euer
Hans
Re: BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Donnerstag 22. März 2012, 09:12
von BlackJack
@hans.mueller1206: Wo liegt denn das Problem? Funktioniert der Code hier nicht mehr? Denn die Tabellen scheinen gleich aufgebaut zu sein. Die Webseiten unterscheiden sich nur durch die Liga-ID in der URL.
Re: BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Donnerstag 22. März 2012, 10:37
von deets
Dafuer darfst du ein neues Thema aufmachen. Und uns erstmal zeigen, was du schon probiert hast.
Re: BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Donnerstag 22. März 2012, 12:00
von hans.mueller1206
Ich muss gestehen ich kenne mich nicht unbedingt gut aus mit Python, daher habe ich selbst noch nicht viel versucht bzw. gar nichts

!
Aber folgende Plugin hat ein mir jmd. zu gesand:
Code: Alles auswählen
import re
import sys
import urllib2, urllib
import json
from plugin import *
try:
from imdb import IMDb
import imdb.helpers
except ImportError:
raise NecessaryModuleNotFound("Oops! Unable to locate the IMDb library. Please install IMDbPy. e.g. (sudo easy_install IMDbPy) or (sudo apt-get install python-imdbpy)")
class nurf_imdb(Plugin):
@register("de-DE", "(Film)* ([\w ]+)")
def get_director(self, speech, language, regex):
if language == "de-DE":
MovieTitle = regex.group(regex.lastindex).strip()
ia = IMDb()
search_result = ia.search_movie(MovieTitle)
if not search_result:
self.say("Leider keinen Film gefunden mit: " + MovieTitle)
self.complete_request()
else:
movie_info = search_result[0]
ia.update(movie_info)
MovieRating = movie_info['rating']
try:
mpaalala = movie_info['mpaa']
mpaalala = re.match("Rated ([\w ]+) for", mpaalala, re.IGNORECASE)
mpaalala = mpaalala.group(1).strip()
if mpaalala == 'R':
mpaalala = 'ab 16, '
if mpaalala == 'PG':
mpaalala = 'ab 6, '
if mpaalala == 'PG-13, ':
mpaalala = 'ab 12'
if mpaalala == 'NC-17, ':
mpaalala = 'ab 18, '
if mpaalala == 'G':
mpaalala = 'ab 0, '
except:
mpaalala = ''
self.say(movie_info['title'] + " (" + str(movie_info['year']) + ", " + mpaalala + "Wertung: "+ str(MovieRating) +") ")
self.complete_request()
und so ähndlich müsste das mit dem Bundesliga Plugin ja auch gehen... ich hoffe auf Hilfe

!
Gruß
Hans
Re: BeautifulSoup Tabelle auslesen (SIS-Handball)
Verfasst: Donnerstag 22. März 2012, 12:59
von deets
Bitte:
- eigenen thread aufmachen, nicht einen 3 jahre alten hi-jacken
- python-code-tags benutzen. so kann man nix lesen!!!