2010-01-03 5 views
7

Je pensais écrire un code rapide pour télécharger le nombre de "fans" d'une page Facebook.Caractère générique correspondant à une chaîne dans Python regex search

Pour une raison quelconque, malgré un bon nombre d'itérations j'ai essayé, je ne peux pas obtenir le code suivant pour choisir le nombre de fans dans le HTML. Aucune des autres solutions trouvées sur le web ne correspond à la regex dans ce cas non plus. Sûrement il est possible d'avoir un caractère générique entre les deux bits correspondants?

Le texte que je voudrais comparer est "6 of X fans", où X est un nombre arbitraire de fans une page a - Je voudrais obtenir ce nombre.

Je pensais interroger ces données par intermittence et écrire dans un fichier, mais je n'ai pas encore eu l'occasion de le faire. Je me demande également si cela va dans la bonne direction, car le code semble assez maladroit. :)

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

* ne semble pas fonctionner * n'est pas un problème description –

+0

sidenote: vous devriez nommer 'lines' 'line' – miku

+1

Veuillez poster le texte que vous essayez de faire correspondre et (si possible) le résultat que vous attendez. – Mike

Répondre

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() 

Vous nécessaire d'utiliser re.search() à la place. L'utilisation de re.match() essaie de faire correspondre le motif au document entier, mais vous essayez simplement de faire correspondre une pièce dans le document. Le code ci-dessus s'imprime: 79,110. Bien sûr, ce sera probablement un nombre différent au moment où il est géré par quelqu'un d'autre.

+1

merci beaucoup - fonctionne très bien. Je ne suis pas sûr de bien comprendre la distinction - match() serait utilisé dans les cas où une sorte d'évaluation bool était faite sur une petite chaîne (ish)? – oneAday

+2

@oneAday: bonne explication de la différence entre 'match' et' search': http://www.amk.ca/python/howto/regex/regex.html#SECTION000720000000000000000 – bernie

+0

@oneAday: pourquoi ne pas accepter cette réponse si travaille pour vous? – bernie

0

ne ont pas besoin regex

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] 

sortie

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

Evan Fosmark a déjà donné une bonne réponse. Ceci est juste plus d'informations.

Vous avez cette ligne:

pattern = "6 of(.*)fans" 

En général, ce n'est pas une bonne expression régulière. Si le texte d'entrée était:

« 6 de 99 fans dans toute la galaxie de fans »

Ensuite, le groupe de correspondance (la substance à l'intérieur des parenthèses) serait:

"99 fans dans l'ensemble Donc, nous voulons un modèle qui va juste attraper ce que vous voulez, même avec un texte d'entrée idiot comme le ci-dessus.

Dans ce cas, cela n'a pas vraiment d'importance si vous faites correspondre l'espace blanc, car lorsque vous convertissez une chaîne en nombre entier, l'espace blanc est ignoré. Mais écrivons le motif pour ignorer l'espace blanc.

Avec le caractère générique *, il est possible de faire correspondre une chaîne de longueur zéro. Dans ce cas, je pense que vous voulez toujours une correspondance non vide, donc vous voulez utiliser + pour faire correspondre un ou plusieurs caractères.

Python a une correspondance non gourmande disponible, donc vous pouvez réécrire avec ça. Les anciens programmes avec des expressions régulières peuvent ne pas avoir de correspondance non gourmande, donc je vais aussi donner un modèle qui ne nécessite pas de non-gourmande.

Ainsi, le motif non gourmand:

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

L'autre:

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

\s signifie "tout espace blanc" et correspondra à un espace, un onglet, et quelques autres caractères (tels que "flux de formulaire"). \S signifie "tout espace non-blanc" et correspond à tout ce que \s correspondrait pas correspondre.

Le premier modèle fait mieux que votre premier modèle avec le texte d'entrée stupide:

« 6 de 99 ventilateurs dans la galaxie entière de fans »

Il retournerait un groupe de match juste 99.

Mais essayez cet autre texte d'entrée stupide:

"6 de 99 fans de fous"

Il retournerait un groupe de match 99 crazed.

Le deuxième motif ne correspondrait pas du tout, car le mot "fou" n'est pas le mot "ventilateurs".

Hmm. Voici un dernier modèle qui devrait toujours faire la bonne chose, même avec des textes d'entrée stupides:

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

\d correspond à un chiffre ('0'-'9'). \D correspond à un non-chiffre.

Cela correspondra avec succès tout ce qui est à distance non-ambiguë:

"6 de 99 ventilateurs dans toute la galaxie des fans"

Le groupe de match sera 99.

"6 de 99 fans de" fous

Le groupe de correspondance sera 99.

"6 de 99 41 fans"

Il ne correspond pas à, parce qu'il y avait un deuxième nombre là-bas. Pour en savoir plus sur les expressions régulières Python, vous pouvez lire variouswebpages. Pour un petit rappel, l'intérieur de l'interpréteur Python, faites:

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

Lorsque vous texte « grattant » à partir d'une page Web, vous pouvez parfois aller à l'encontre des codes HTML. En général, les expressions régulières ne sont pas un bon outil pour ne pas tenir compte du balisage HTML ou XML (voir here); vous feriez probablement mieux d'utiliser Beautiful Soup pour analyser le code HTML et extraire le texte, suivi d'une expression régulière pour saisir le texte que vous vouliez vraiment.J'espère que ce fut intéressant et/ou éducatif.

+0

+1 pour la largeur et le volume – bernie

+0

intéressant et éducatif - fantastique. Merci beaucoup. – oneAday

Questions connexes