Nach Links suchen

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
Stegi95
User
Beiträge: 12
Registriert: Freitag 29. Oktober 2010, 13:03

Hey Leute,
ich habe (wieder einmal) eine Frage wegen re...

Hier zum Problem: Ich habe einen String mit dem Quelltext einer zuvor geöffneten Seite. Ich möchte aus diesem String alle Links raussuchen(also nur die verlinkte Seite, nicht das ganze mit <a href=...> sondern nur die Seite hinter dem a href ). Das macht man ja normalerweise mit re.findall(). Dafür bin ich allerdings zu dumm... Könnt ihr mir da helfen? Die Links sollen am besten in einem Array gespeichert werden ;)

Danke schonmal im Vorraus

PS: Ich möchte keine 3rd Party Module benutzen, also bitte empfehlt mir nicht Beautiyful Soup und co...
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Stegi95 hat geschrieben:Hey Leute,
ich habe (wieder einmal) eine Frage wegen re...

Hier zum Problem: Ich habe einen String mit dem Quelltext einer zuvor geöffneten Seite. Ich möchte aus diesem String alle Links raussuchen(also nur die verlinkte Seite, nicht das ganze mit <a href=...> sondern nur die Seite hinter dem a href ). Das macht man ja normalerweise mit re.findall(). Dafür bin ich allerdings zu dumm... Könnt ihr mir da helfen? Die Links sollen am besten in einem Array gespeichert werden ;)
Bei re.findall() werden die Treffer schon als Array gespeichert.
Du könntest sowas in der Art machen:

Code: Alles auswählen

re.findall('<a .* href=".*"', source_code)
Musst halt noch den Rest wegmachen (<a href=")
karolus
User
Beiträge: 141
Registriert: Samstag 22. August 2009, 22:34

Hallo

Vielleicht solltest du dann besser gleich:

Code: Alles auswählen

re.findall(r'''a href="(.+?)">''', seiten_quelltext)
nehmen.

Gruß Karo
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Eigentlich kann man mit regulären Ausdrücken nicht vernünftig HTML parsen. Wenn du weißt, dass deine Eingabe gültiges XHTML ist, könntest du Pythons eingebauten XML-Parser benutzen. Reguläre Ausdrücke können nur ein Notbehelf sein. Hier ein Beispiel für Python 3.1. Beachte, dass die gefundene URL noch Entities (z.B. &) enthalten kann, die noch entfernt werden müssten.

Code: Alles auswählen

import re, urllib.request
from urllib.parse import urljoin

b = "http://python-forum.de"
s = urllib.request.urlopen(b).read().decode('utf-8')

def get_a(b, s):
    for m in re.finditer(r"""(?is)<a[^>]*href[\s\n]*=[\s\n]*("[^"]*"|'[^']*')""", s):
        yield urljoin(b, m.group(1)[1:-1])

print(list(get_a(b, s)))
Stefan
Zuletzt geändert von sma am Samstag 20. November 2010, 11:30, insgesamt 1-mal geändert.
lunar

@OP: "lxml.html" sollte dennoch erwähnt werden, auch wenn Du keine Drittmodule nutzen möchtest. Es ist die beste Lösung zur Arbeit mit HTML, und bietet insbesondere auch komfortable Methoden für Verarbeitung von Links.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Uh, wow. Mit nem XML-Parser geht das ja super! Aber natürlich nur für valides XML :)

Code: Alles auswählen

import xml.parsers.expat

def start_element(name, attrs):
    if name == 'a':
        links.append(attrs['href'])

links = []
p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = start_element

with open("irgendeine_datei.xml", "r") as f:
    p.Parse(f.read())
lunar

@nomnom: Verwende statt expat, sax oder minidom doch ElementTree.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

lunar hat geschrieben:@nomnom: Verwende statt expat, sax oder minidom doch ElementTree.
Wieso denn? Tu ich nicht, wenn mir nicht gesagt wird wieso ;)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

nomnom hat geschrieben:
lunar hat geschrieben:@nomnom: Verwende statt expat, sax oder minidom doch ElementTree.
Wieso denn? Tu ich nicht, wenn mir nicht gesagt wird wieso ;)
Ist auch in diesem Fall kein guter Tipp, denn alles DOM-artige saugt sich das gesamte Dokument in den Hauptspeicher, was zum Finden von a[href] nun wirklich nicht notwendig ist. Hier ist das SAX-API auch nicht wirklich kompliziert zu benutzen.

Stefan
BlackJack

@nomnom: Die `ElementTree`-API ist nicht so ekelig Java-artig.

@sma: Die `iterparse()`-Funktion legt kein DOM an.

Edit: So könnte das ohne DOM mit `ElementTree` aussehen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from xml.etree import ElementTree as etree


def main():
    result = list()
    for _type, node in etree.iterparse('test.xml', ['start']):
        if node.tag == 'a':
            result.append(node.get('href'))
    print result


if __name__ == '__main__':
    main()
Stegi95
User
Beiträge: 12
Registriert: Freitag 29. Oktober 2010, 13:03

@sma

Mit deiner Methode klappt es bestens ;)

Aber, was kann ich tun, wenn ich nicht weiß, ob die Seite valides XHTML ist? Wenn ich zum Beispiel die Seiten automatisch aufrufen lasse, und dann scnnen lasse...dann weiß ich ja nicht, ob es gutes, reines XHTML ist.

Danke aber schonmal an alle, das geht wirklich fix hier
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

@Lunar und BlackJack:

Code: Alles auswählen

import xml.etree.ElementTree

tree = xml.etree.ElementTree.parse("beispiel.xml")
links = tree.getiterator("a")
for link in links:
    print link.get("href")
Ja, ist kürzer und schöner, stimmt
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Stegi95 hat geschrieben:Aber, was kann ich tun, wenn ich nicht weiß, ob die Seite valides XHTML ist? Wenn ich zum Beispiel die Seiten automatisch aufrufen lasse, und dann scnnen lasse...dann weiß ich ja nicht, ob es gutes, reines XHTML ist.
Ein nicht valides XML-Dokument muss einen validierenden XML-Parser einen Fehler werfen lassen. Daran kann man's dann erkennen. Nützen tut es natürlich recht wenig, wenn man trotzdem die Links ermitteln will. Dann hilft vielleicht immer noch der reguläre Ausdruck.

Stefan
Stegi95
User
Beiträge: 12
Registriert: Freitag 29. Oktober 2010, 13:03

Also macht man mit Exeptions, oder? Ich kenn mich da noch nicht sooo mit aus...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ja. Oder echt mal lxml.html oder zumindest html5lib nutzen. Letztere benötigt auch keinen C-Code, kann also der Applikation zur Not mitgeliefert werden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten