BeautifulSoup Wikipedia parsen

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
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Code: Alles auswählen

import requests
from BeautifulSoup import BeautifulSoup as soup
import pprint

url = "http://de.wikipedia.org/wiki/Liste_der_chemischen_Elemente"
data = requests.get(url).text
soup = soup(data)

elemente = {}

for x in range(0, 250, 2):
    try:
        elemente[str(soup("td", {"align": "left"})[x].a.string)] = [
            str(soup("td", {"align": "right"})[x].string),
            str(soup("td", {"align": "right"})[x].string)
        ]
    except IndexError:
        continue

pprint.pprint(elemente)
Habe gerade das Modul BeautifulSoup entdeckt. Echt coole Sache, aber leider schaffe ich es nicht, den Elementen des PSE Schmelz- und Siedetemperatur zuzuordnen. Wie kann man das machen?
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Wo liegt denn da das Problem?
Jede Zeile hat den Tag tr und die wiederum besteht aus einer festen Anzahl von td Tags.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@Xfd7887a

falls Du sowas öfter brauchst, Wikipedia bietet auch eine API:
http://www.mediawiki.org/wiki/API

Die kann u.a. JSON zurückliefern, was viel einfacher und verlässlicher zu parsen ist ;-)
BlackJack

@mcdwerner: Wie soll das einfacher sein? Dann bekommt man halt JSON zurück was die Wikiseite als *HTML* enthält. Also muss man auch in diesem Fall die Informationen aus dem HTML parsen, nur dass man noch einen zusätzlichen Schritt vorher mit dem JSON hat, statt direkt das HTML abzufragen. Ich sehe den Gewinn nicht. Die API ist nützlich wenn man Metainformationen über die Seiten einfacher haben möchte als sie aus dem HTML zu kratzen.

@Xfd7887a: Um sich die Struktur von Webseiten anzuschauen und welche Attribute man zum identifizieren von Elementen verwenden kann, kann man entsprechende Plugins für den Browser verwenden. Bei Firefox zum Beispiel die bereits eingebauten Web Developer Tools oder Firebug (+ diverse Erweiterungen).
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@Blackjack: die API liefert nicht nur html zurück, sondern u.a. auch das eigene "Wikimedia Format":
als xml:
http://de.wikipedia.org/w/api.php?actio ... n_Elemente
als json:
http://de.wikipedia.org/w/api.php?actio ... ormat=json

dieses Wikimedia Format muss man natürlich auch nochmal parsen, für mich hat sich die Einarbeitung darin gelohnt, deswegen auch nur "wenn Du das öfter brauchst" ;-)
BlackJack

@mcdwerner: Statt einen fertigen HTML-Parser auf eine HTML-Tabelle loszulassen wobei von der Struktur her HTML eher Richtung maschinelle Verarbeitung optimiert ist, soll man sich mit dem Parsen von Wikimarkup beschäftigen was von der Struktur eher auf den menschlichen Schreiber optimiert ist? Auch ein „wenn man das öfter braucht”-Zusatz macht da keinen Sinn.

Solange man keine Informationen benötigt die beim rendern als HTML verloren gehen, oder dort nicht mehr so einfach abfragbar sind, ist es soweit ich das sehe immer einfacher das HTML auszuwerten als den Wikitext zu parsen. Selbst wenn man einen fertigen Mediawiki-Parser verwendet, fehlen einem ja noch die Such- und Navigationsmöglichkeiten die BeautifulSoup oder `lxml.html` bieten.

Oder mal als Code ausgedrückt:

Code: Alles auswählen

from collections import namedtuple
import requests
from bs4 import BeautifulSoup


Element = namedtuple(
    'Element', 'name symbol atomic_number weight density melt boil'
)


def parse_float(string):
    if not string.strip():
        return float('nan')
    if string.startswith(u'\N{MINUS SIGN}'):
        string = '-' + string[1:]
    return float(string.replace(',', '.'))


def parse_element_table(html_source):
    soup = BeautifulSoup(html_source)
    parsers = (
        unicode,
        unicode,
        int,
        parse_float,
        parse_float,
        parse_float,
        parse_float,
    )
    for row in soup.find('table', 'wikitable').tr.find_next_siblings('tr'):
        yield Element(*(p(c.text) for p, c in zip(parsers, row('td')[:7])))


def main():
    url = 'http://de.wikipedia.org/wiki/Liste_der_chemischen_Elemente'
    response = requests.get(url)
    elements = list(parse_element_table(response.text))
    print elements



if __name__ == '__main__':
    main()
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Danke für die Antworten :D!
Antworten