Seite 1 von 1

Links aus einer Seite auslesen mit BeautifulSoup

Verfasst: Sonntag 14. Oktober 2007, 19:09
von joker21
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

Verfasst: Sonntag 14. Oktober 2007, 19:39
von BlackJack
Erster Tipp: Das ist syntaktisch falsch. Und ich bekomme bei der Seite einen 500er Fehler!?

Verfasst: Sonntag 14. Oktober 2007, 20:01
von joker21
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.

Verfasst: Sonntag 14. Oktober 2007, 20:04
von joker21
Übrigens muss es auch bei "source = urlopen" nicht "html" heißen, sondern "php". Ich hatte das richtig gepostet. Warum wird das automatisch umgewandelt?

Verfasst: Sonntag 14. Oktober 2007, 21:00
von 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()

Verfasst: Mittwoch 17. Oktober 2007, 07:31
von joker21
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:
...

Verfasst: Samstag 3. November 2007, 13:45
von joker21
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?

Verfasst: Samstag 3. November 2007, 14:41
von BlackJack
Weil die Methode so definiert ist, dass man als zweites Argument ein Dictionary mit Attributname->Werten übergeben kann!?

Verfasst: Samstag 3. November 2007, 17:45
von joker21
Gibt es irgendwo ein Tutorial für BS jenseits der Dokumentation?

Verfasst: Samstag 3. November 2007, 19:33
von Leonidas
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.

Verfasst: Sonntag 4. November 2007, 15:42
von joker21
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.

Verfasst: Sonntag 4. November 2007, 16:41
von Leonidas
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`, ...).