Links aus einer Seite auslesen mit BeautifulSoup

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
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

Hallo,

es geht um die Tabelle "Editionen" rechts unten auf dieser Seite:
http://www.miraclegames.de/d/shopindex.html?id=0100

Ich möchte die Link-Adressen die hinter den diversen "R" "U" und "C" liegen auslesen und in eine Datei speichern. Das sollte mit Beautifulsoup machbar sein. Aber ich bekomme es nicht nicht.
Der Anfang ist noch klar:

Code: Alles auswählen

from BeautifulSoup import BeautifulSoup
from urllib2 import urlopen
source = urlopen(http://www.miraclegames.de/d/shopindex.html?id=0100)
soup = BeautifulSoup(source)
Aber leider schaffe ich es nicht nun die Tabelle zu lokalisieren und die darin liegenden Links.

Danke für jeden Tipp!

Jochen
BlackJack

Erster Tipp: Das ist syntaktisch falsch. Und ich bekomme bei der Seite einen 500er Fehler!?
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

BlackJack hat geschrieben:Erster Tipp: Das ist syntaktisch falsch. Und ich bekomme bei der Seite einen 500er Fehler!?
Hm... zwei Dreckfuhler.

Hochkommas fehlen natürlich. Mein Fehler.

Aber der Link muss statt "html" "php" heißen. Interessanterweise kann ich die URL hier so oft einfügen, wie ich will. Die Forensoftware ersetzt immer das "php" durch "html". Sehr seltsam.

Also bitte die URL bitte richtig in den Browser eingeben.
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

Übrigens muss es auch bei "source = urlopen" nicht "html" heißen, sondern "php". Ich hatte das richtig gepostet. Warum wird das automatisch umgewandelt?
BlackJack

Hässliche Seite. Also was das HTML angeht. Hier ein Versuch:

Code: Alles auswählen

from pprint import pprint
from BeautifulSoup import BeautifulSoup


def iter_links(soup):
    editionen_table = soup.find('table', dict(id='bgednav1r'))
    content_table = editionen_table.findNextSibling('table').table
    for row in content_table('tr'):
        text = row.td(text=True)[0].strip()
        links = dict((a(text=True)[0], a['href']) for a in row('a'))
        if links:
            yield (text, links)


def main():
    in_file = open('test.html', 'r')
    source = in_file.read()
    in_file.close()
    
    soup = BeautifulSoup(source, convertEntities=BeautifulSoup.HTML_ENTITIES)
    result = dict(iter_links(soup))
    pprint(result)


if __name__ == '__main__':
    main()
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

Hallo BlackJack,

danke, für den "Tipp". Ich komme gerade nicht dazu, werde aber in den nächsten Tagen schauen und feedback geben.

Jochen
BlackJack hat geschrieben:Hässliche Seite. Also was das HTML angeht. Hier ein Versuch:
...
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

BlackJack hat geschrieben:Hässliche Seite. Also was das HTML angeht.
Das führte dazu, dass ich mich nicht wirklich zurecht fand. Ich hatte schon die Tabelle mit der id 'bgednav1r' als Anhaltspunkt ausgemacht. Aber es war mir nicht gelungen, darauf vernünftig zuzugreifen.

Code: Alles auswählen

editionen_table = soup.find('table', dict(id='bgednav1r'))
Wieso verwendest Du hier ein dictionary?
BlackJack

Weil die Methode so definiert ist, dass man als zweites Argument ein Dictionary mit Attributname->Werten übergeben kann!?
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

Gibt es irgendwo ein Tutorial für BS jenseits der Dokumentation?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

joker21 hat geschrieben:Gibt es irgendwo ein Tutorial für BS jenseits der Dokumentation?
Nein, aber du kannst im Internet schauen, dort findet man manchmal Blogposts mit kleinen Snippets (oder hier im Forum per Suchfunktion). Aber ich sehe eigentlich dein Problem nicht, die Dokumentation dafür ist ziemlich unfassend.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
joker21
User
Beiträge: 17
Registriert: Sonntag 14. Oktober 2007, 11:36

Ok, ich versuche anhand der Dokumentation diese Zeile nachzuvollziehen:

Code: Alles auswählen

editionen_table = soup.find('table', dict(id='bgednav1r'))
Es geht doch darum, als ersten Anlaufpunkt die Tabelle zu finden, die eben diese id hat. Und von da aus die nächste Tabelle, die eben die ist, in denen die Links stehen. Aber warum dann nicht einfach

Code: Alles auswählen

editionen_table = soup.find('table', id='bgednav1r')
Das bewirkt doch das gleiche. Von das aus weiter die nächste Tabelle anspringen. In einer Zeile sähe das so aus:

Code: Alles auswählen

soup.find('table', id='bgednav1r').findNextSibling('table')
Ich verstehe leider immer noch nicht, was das dict dort bewirkt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Es bewirkt nichts zusätzlich, es ist einfach nur eine Alternative:
BeautifulSoup Dokumentation hat geschrieben:You can use attrs if you need to put restrictions on attributes whose names are Python reserved words, like class, for, or import; or attributes whose names are non-keyword arguments to the Beautiful Soup search methods: name, recursive, limit, text, or attrs itself.
Es hilft aber wenn du nach Dingen suchst, die reservierte Worte in Python sind. Dann kannst du sie einfach als String in einem Dict angeben. Ebenso wenn du nach einem für BeautifulSoup reservierten Parameter suchst (also `name`, `recursive`, ...).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten