Regulärer Ausdruck macht Probleme

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
Area51
User
Beiträge: 27
Registriert: Donnerstag 24. Juli 2008, 11:38
Wohnort: Heidelberg
Kontaktdaten:

Hallöle :)
1. Post und gleich ne dumme Frage *g*

Ich lasse mit den Modulen "BeautifulSoup", "html2text" und "urllib2" diverse Links aus einem Menü auslesen. Diese Kategorien besitzen nun Unterkategorien.

Das Auslesen der Hauptkategorien ist nicht sonderlich schwer, doch die Unterkategorien wollen nicht so recht.

Mit dem Pattern

Code: Alles auswählen

linkPattern = 'href="(.*?)"'
lasse ich alle Grundlinks auslesen.
Schematisch sind diese etwa so aufgebaut:
file.php?x=katId&sid=wasweisich&sonstiges=bla

Die Unterkategoren haben einen ähnlichen Aufbau:
file.php?x=katId&y=katId2&sid=wasweisich&sonstiges=bla

Oder auch:
file.php?y=katId2&x=katId&sid=wasweisich&sonstiges=bla

Die Links der Kategorien lassen sich prima auslesen, mit print erhalte ich diese Ausgabe:
['/shop/migal/limashop0/menu.php?x=0&sid=48885fcd63a5f&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?y=16&x=0&sid=48885fcd63a5f&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?y=17&x=0&sid=48885fcd63a5f&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?y=18&x=0&sid=48885fcd63a5f&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0']
Doch nun das Hauptproblem: Ich benötige hier nur Links, die die Parameter x UND y enthalten.

Dazu hab ich diesen regulären Ausdruck gebastelt:

Code: Alles auswählen

subCatPattern = '(.*?)y=([0-9]{1,})&x=([0-9]{1,})(.*)|(.*?)x=([0-9]{1,})&y=([0-9]{1,})(.*)'
Wenn ich besagte Links in dieser Form auslesen möchte

Code: Alles auswählen

subMenuTemp = re.findall (linkPattern, soupCats)
subMenuTemp = re.findall (subCatPattern, str (subMenuTemp) )
print subMenuTemp
erhalte ich diese Ausgabe:
[("['/shop/migal/limashop0/menu.php?x=0&sid=4888609e3de12&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?", '16', '0', "&sid=4888609e3de12&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?y=17&x=0&sid=4888609e3de12&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0',
'/shop/migal/limashop0/menu.php?y=18&x=0&sid=4888609e3de12&iproj=limainst&isprach=&adz=&mit1aufruf=1&mitstrich=0']", '', '', '', '')]
Ja, jetzt hab ich Anstatt den Links zu den Unterkategorien die Links zu den Dateien und die Parameter x und y getrennt. Theoretisch könnte ich diese Teile zusammensetzen, doch die Parameter x und y sind nicht immer in der gleichen Reihenfolge gegeben.

Wenn jemand die Lösung weiß oder mit ansonsten helfen kann, würde ich mich sehr freuen :)

Wenn nötig, könnte ich die Datei auch zur Verfügung stellen
lunar

Ganz grundsätzlich gehst du an die Aufgabe falsch heran. Reguläre Ausdrücke sind dafür nur bedingt geeignet. Im Übrigen lässt mich die Tatsache, dass du "html2text" verwendest, um Links auszulesen, Schlimmstes befürchten. Du übersetzt doch nicht allen Ernstes HTML-Code in Plain-Text, um darauf dann mit regulären Ausdrücken zu arbeiten? :shock:

Im Allgemeinen solltest du so vorgehen. Mit BeautifulSoup nach Knoten mit href-Attribut suchen, dieses Attribute auslesen, aus der resultierenden URL mit "urlparse.urlsplit" den Query-Teil extrahieren, und diesen Query-Teil dann mit "cgi.parse_qs" auseinander nehmen. Dann hat sich die Prüfung, ob ein Link Parameter "X" und Parameter "Y" enthält, nämlich auf eine simple If-Abfrage auf dem von "cgi.parse_qs" zurückgegebenen Dictionary reduziert.
Area51
User
Beiträge: 27
Registriert: Donnerstag 24. Juli 2008, 11:38
Wohnort: Heidelberg
Kontaktdaten:

Ups, html2text hab ich garnicht drin, wie bin ich da drauf gekommen? *g*

Und wieso bin ich nicht draufgekomme, das ich mit soup den href-Knoten auslesen kann ? *Kopf an die Wand hau*

Danke für die Hilfe, ich schau mal, was ich schaffe :)
Area51
User
Beiträge: 27
Registriert: Donnerstag 24. Juli 2008, 11:38
Wohnort: Heidelberg
Kontaktdaten:

Sodele, ich habe es über den einfacheren Weg lunar geschafft *g* Doch nun hab ich ein Problem, von dessen Ursprug ich mir kein Bild machen kann.

Zum prüfen, ob bestimmte Parameter in einer URL existieren, habe ich mir eine Funktion gebastelt:

Code: Alles auswählen

def checkUrlParams (url, params):
    boolean     = 0
    parse       = urlparse (url)
    urlparams   = cgi.parse_qs (parse.query)

    for i in range (len (params) ):
        if hasattr (urlparams, params[i]):
            boolean = True
        else:
            boolean = False

    return boolean
Diese soll prüfen, ob die gesuchten Parameter in einer URL existieren oder nicht.

Nur bekomm ich immer False, auch wenn die Parameter definitiv existieren.

Aufgerufen wird die Funktion folgendermassen:

Code: Alles auswählen

### Parameter vorhanden?
if checkUrlParams (subCats[counter], ['x', 'y']):
    print 'test'
In subCats befinden sich alle aufzurufenden URLs. Als Test habe ich nur nach dem Parameter "x" suchen lassen, der ja in jedem Link vorhanden ist, aber trotzdem bekomm ich nur False.

Ist das ein Bug in hasattr () oder bin ich zu doof? *g*
lunar

Area51 hat geschrieben:

Code: Alles auswählen

def checkUrlParams (url, params):
    boolean     = 0
    parse       = urlparse (url)
    urlparams   = cgi.parse_qs (parse.query)

    for i in range (len (params) ):
        if hasattr (urlparams, params[i]):
            boolean = True
        else:
            boolean = False

    return boolean
[...]
Ist das ein Bug in hasattr () oder bin ich zu doof? *g*
Letzteres (nichts für ungut). Wie ich schon sagte, "cgi.parse_qs" liefert ein Dictionary zurück. Wenn dir das nichts sagt, dann lies das Tutorial, da wird das erklärt.

Im Übrigen ist dein Vergleich recht aufwendig und unpythonisch und noch dazu schlichtweg falsch. Er gibt auch dann True zurück, wenn gar nicht alle Parameter enthalten sind. Warum das so ist, darfst du selbst herausfinden.

Eigentlich ist das ein Zweizeiler:

Code: Alles auswählen

def has_params(url, params):
    query = cgi.parse_qs(url)
    return all(p in query for p in params)
Dafür lohnt auch keine eigene Funktion ...
Area51
User
Beiträge: 27
Registriert: Donnerstag 24. Juli 2008, 11:38
Wohnort: Heidelberg
Kontaktdaten:

Hmm, mit deiner Funktion bekomm ich immernoch False zurück.

Und wenn ich hasattr () direkt benutze, also

Code: Alles auswählen

if hasattr (params, 'x'):
  print 'bla'
else:
  print 'foo'
bekomm ich nur 'foo' ausgespuckt...

Ich komm eigentlich aus der PHP-Fraktion und deshalb packe ich Dinge, die man mehrmals brauchen kann gleich in eine Funktion *g*
lunar

Area51 hat geschrieben:Hmm, mit deiner Funktion bekomm ich immernoch False zurück.

Code: Alles auswählen

>>> import cgi
>>> query = cgi.parse_qs('y=katId2&x=katId&sid=wasweisich&sonstiges=bla')
>>> params = ['y', 'x']
>>> all(p in query for p in params)
True
Die Funktion funktioniert, wenn man sie richtig aufruft. Da du aber deinen Aufruf nicht gezeigt hast, kann man über den Fehler nur rätseln.
Und wenn ich hasattr () direkt benutze, also

Code: Alles auswählen

if hasattr (params, 'x'):
  print 'bla'
else:
  print 'foo'
bekomm ich nur 'foo' ausgespuckt...
Ich kann mich nur wiederholen: Wenn dich das wundert, dann arbeite das Tutorial durch. "params" ist ein Dictionary. Das hat vielleicht ein Element "x", aber mit Sicherheit kein Attribut "x", weswegen der Test mit "hasattr" natürlich ins Leere läuft. Und wie gesagt, wenn dir das nichts sagt, hilft das Tutorial, insbesondere Abschnitt 5.6.
Ich komm eigentlich aus der PHP-Fraktion und deshalb packe ich Dinge, die man mehrmals brauchen kann gleich in eine Funktion *g*
Funktionen dienen dazu, Komplexität durch Abstraktion zu verringern, nicht sie durch unnötigen Mehraufwand zu erhöhen.
Area51
User
Beiträge: 27
Registriert: Donnerstag 24. Juli 2008, 11:38
Wohnort: Heidelberg
Kontaktdaten:

Ich bin ein Pferd *lol*

Man sollte auch die komplette URL übergeben und nicht nur die Datei mit dem Parametern *wallbash*
Das ist der Fehler gewesen, weshalb deine Funktion nicht wollte.

Danke für deine Geduld mit mir :)
Antworten