2010-01-03 9 views
7

Ich dachte, ich würde einen schnellen Code schreiben, um die Anzahl der "Fans" eine Facebook-Seite herunterladen.Wildcard, die eine Zeichenfolge in Python Regex Suche

Aus irgendeinem Grund, trotz einer guten Anzahl von Iterationen, die ich versucht habe, kann ich nicht den folgenden Code abrufen, um die Anzahl der Fans im HTML auszuwählen. Keine der anderen Lösungen, die ich im Internet gefunden habe, stimmt auch in diesem Fall mit der Regex überein. Sicherlich ist es möglich, ein Wildcard zwischen den beiden passenden Bits zu haben?

Der Text, mit dem ich übereinstimmen möchte, ist "6 X-Fans", wo X ist eine beliebige Anzahl von Fans eine Seite hat - ich möchte diese Nummer bekommen.

Ich dachte daran, diese Daten intermittierend abzufragen und in eine Datei zu schreiben, aber ich bin noch nicht dazu gekommen. Ich frage mich auch, ob dies in die richtige Richtung geht, da der Code ziemlich klobig wirkt. :)

import urllib 
import re 

fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft') 
pattern = "6 of(.*)fans" #this wild card doesnt appear to work? 
compiled = re.compile(pattern) 

for lines in fbhandle.readlines(): 
     ms = compiled.match(lines) 
     print ms #debugging 
     if ms: break 
#ms.group() 
print ms 
fbhandle.close() 
+1

* scheint nicht zu funktionieren * ist kein Problem Beschreibung –

+0

sidente: Sie sollten 'Linien' 'Linie' nennen – miku

+1

Bitte senden Sie den Text, den Sie versuchen zu vergleichen und (wenn möglich) das Ergebnis erwarten Sie. – Mike

Antwort

9
import urllib 
import re 

fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft') 
pattern = "6 of(.*)fans" #this wild card doesnt appear to work? 
compiled = re.compile(pattern) 

ms = compiled.search(fbhandle.read()) 
print ms.group(1).strip() 
fbhandle.close() 

Sie benötigt re.search() stattdessen zu verwenden. Using re.match() versucht, das Muster gegen das ganze Dokument zu entsprechen, aber wirklich versuchen Sie gerade, ein Stück innerhalb des Dokuments zusammenzubringen. Der obige Code druckt: 79,110. Natürlich wird dies wahrscheinlich eine andere Zahl sein, bis es von jemand anderem ausgeführt wird.

+1

vielen Dank - funktioniert gut. Ich bin mir nicht sicher, ob ich die Unterscheidung wirklich verstehe - match() würde in Fällen verwendet werden, in denen eine Art Booleval auf einer kleinen (ish) Zeichenkette ausgeführt wird? – oneAday

+2

@oneAday: gute Erklärung des Unterschieds zwischen 'match' und' search': http://www.amk.ca/python/howto/regex/regex.html#SECTION000720000000000000000 – bernie

+0

@oneAday: warum nicht diese Antwort akzeptieren, wenn es funktioniert für dich? – bernie

0

nicht regex brauchen

import urllib 
fbhandle = urllib.urlopen('http://www.facebook.com/Microsoft') 
for line in fbhandle.readlines(): 
    line=line.rstrip().split("</span>") 
    for item in line: 
     if ">Fans<" in item: 
      rind=item.rindex("<span>") 
      print "-->",item[rind:].split()[2] 

Ausgang

$ ./python.py 
--> 79,133 
10

Evan Fosmark gab bereits eine gute Antwort. Das ist nur mehr Infos.

Sie haben die folgende Zeile:

pattern = "6 of(.*)fans" 

Generell dieser Ausdruck keine gute regelmäßig ist. Wenn der Eingabetext ist:

"6 von 99 Fans in der ganzen Galaxie von Fans"

Dann wird die Spiel-Gruppe (der Stoff in den Klammern) wäre:

"99 Fans in dem ganzen Galaxie von "

Also, wir wollen ein Muster, das nur greifen wird, was Sie wollen, auch mit einem dummen Eingabetext wie oben.

In diesem Fall spielt es keine Rolle, ob Sie den Leerraum anpassen, da Leerraum bei der Umwandlung einer Zeichenfolge in eine Ganzzahl ignoriert wird. Aber lassen Sie uns das Muster schreiben, um Leerraum zu ignorieren.

Mit dem Platzhalter * ist es möglich, eine Zeichenkette mit der Länge Null abzugleichen. In diesem Fall denke ich, dass Sie immer eine nicht leere Übereinstimmung möchten, also möchten Sie + verwenden, um ein oder mehrere Zeichen zu finden.

Python hat nicht gierige Anpassung zur Verfügung, so dass Sie damit umschreiben könnten. Ältere Programme mit regulären Ausdrücken dürfen nicht gierig sein, daher gebe ich auch ein Muster, das nicht gierig ist.

Also, die nicht gierigen Muster:

pattern = "6 of\s+(.+?)\s+fans" 

Die andere:

pattern = "6 of\s+(\S+)\s+fans" 

\s bedeutet „jeder Leerraum“ und einen Raum passen, eine Registerkarte, und ein paar anderen Zeichen (z. B. "Form Feed"). \S bedeutet "irgendein Nicht-Leerraum" und entspricht allem, was \snicht entspricht.

Das erste Muster tut besser als Ihr erstes Muster mit dem dummen Eingabetext:

„6 von 99 Fans in der ganzen Galaxie von Fans“

Es wäre eine Übereinstimmung Gruppe von nur 99 zurück.

Aber versuchen, diesen anderen dummen Eingabetext:

"6 von 99 verrückten Fans"

Es wäre eine Übereinstimmung Gruppe von 99 crazed zurückzukehren.

Das zweite Muster würde überhaupt nicht passen, weil das Wort "verrückt" nicht das Wort "Fans" ist.

Hmm. Hier ist noch ein letztes Muster, das das Richtige auch mit dummen Eingabetexten immer tun soll:

pattern = "6 of\D*?(\d+)\D*?fans" 

\d entspricht eine beliebige Stelle ('0'-'9'). \D entspricht jeder Nicht-Ziffer.

Dies wird erfolgreich alles akzeptiert, die remote nicht-mehrdeutig ist:

"6 von 99 Fans in der ganzen Galaxie von Fans"

Das Spiel Gruppe 99 sein wird.

"6 von 99 verrückten Fans"

Das Spiel Gruppe wird 99 sein.

"6 von 99 41 Fans"

Es wird nicht passen, weil es eine zweite Zahl in dort war.

Weitere Informationen zu regulären Python-Ausdrücken finden Sie unter variouswebpages. Für eine schnelle Erinnerung, in dem Python-Interpreter, tun:

>>> import re 
>>> help(re) 

Wenn Sie „Schaben“ Text von einer Webseite sind, können Sie manchmal in Konflikt geraten HTML-Codes ausgeführt werden. Im Allgemeinen sind reguläre Ausdrücke kein gutes Werkzeug, um HTML- oder XML-Markup zu ignorieren (siehe here); Sie würden wahrscheinlich besser verwenden, um den HTML-Code zu analysieren und den Text zu extrahieren, gefolgt von einem regulären Ausdruck, um den Text zu erhalten, den Sie wirklich wollten.

Ich hoffe, das war interessant und/oder lehrreich.

+0

+1 für schiere Breite und Volumen – bernie

+0

interessant und pädagogisch - fantastisch. vielen Dank. – oneAday