2010-01-03 16 views
7

Pensé que escribiría un código rápido para descargar la cantidad de "fans" que tiene una página de Facebook.Comodín que coincide con una cadena en la búsqueda de expresiones regulares de Python

Por alguna razón, a pesar de un buen número de iteraciones que he intentado, no puedo obtener el siguiente código para seleccionar la cantidad de fans en el HTML. Ninguna de las otras soluciones que encontré en la web coincide correctamente con la expresión regular en este caso tampoco. ¿Seguramente es posible tener algún comodín entre los dos bits coincidentes?

El texto con el que me gustaría comparar es "6 de X fans", donde X es una cantidad arbitraria de admiradores que tiene una página. Me gustaría obtener este número.

Estaba pensando en sondear estos datos intermitentemente y escribir en un archivo, pero aún no he llegado a eso. También me pregunto si esto va en la dirección correcta, ya que el código parece bastante torpe. :)

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

* no parece funcionar * no es una descripción del problema –

+0

nota al margen: debe nombrar 'líneas' 'línea' – miku

+1

Publique el texto que intenta hacer corresponder y (si es posible) el resultado esperado. – Mike

Respuesta

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

Usted necesita utilizar re.search() lugar. El uso de re.match() intenta hacer coincidir el patrón con el documento completo , pero en realidad solo intenta hacer coincidir una pieza dentro del documento. El código de arriba imprime: 79,110. Por supuesto, este será probablemente un número diferente en el momento en que sea ejecutado por otra persona.

+1

muchas gracias, funciona bien. No estoy seguro de entender por completo la distinción, sin embargo, se usaría match() en los casos en que se realizara algún tipo de evaluación bool en una cadena pequeña (ish). – oneAday

+2

@oneAday: buena explicación de la diferencia entre 'match' y' search': http://www.amk.ca/python/howto/regex/regex.html#SECTION000720000000000000000 – bernie

+0

@oneAday: por qué no aceptar esta respuesta si ¿Funciona para ti? – bernie

0

no necesita de expresiones regulares

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] 

salida

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

Evan Fosmark ya se dio una buena respuesta. Esto es solo mas información.

está esta línea:

pattern = "6 of(.*)fans" 

En general, esto no es una buena expresión regular. Si el texto de entrada era:

"6 de 99 aficionados en toda la galaxia de los aficionados"

A continuación, el grupo de juego (lo que hay dentro de los paréntesis) sería:

"99 aficionados en el conjunto galaxy of "

Por lo tanto, queremos un patrón que solo atrape lo que desee, incluso con un texto de entrada tonto como el anterior.

En este caso, no importa si coincide con el espacio en blanco, porque cuando convierte una cadena en un número entero, se ignora el espacio en blanco. Pero vamos a escribir el patrón para ignorar el espacio en blanco.

Con el comodín *, es posible hacer coincidir una cadena de longitud cero. En este caso, creo que siempre quiere una coincidencia no vacía, por lo que desea utilizar + para que coincida con uno o más caracteres.

Python tiene una coincidencia no codiciosa disponible, por lo que puede volver a escribir con eso. Los programas más antiguos con expresiones regulares pueden no tener coincidencias no codiciosas, por lo que también daré un patrón que no requiera no codicioso.

Así, el patrón no expansivo:

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

El otro:

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

\s significa "cualquier espacio en blanco" y coincidirá con un espacio, un tabulador, y algunos otros caracteres (como "alimentación de formulario"). \S significa "cualquier espacio no blanco" y coincide con cualquier cosa que \s sería no coincida con.

El primer patrón lo hace mejor que su primer patrón con el texto de entrada tonta:

"6 de 99 ventiladores en toda la galaxia de los aficionados"

Se volvería un grupo fósforo de poco 99.

Pero tratar este otro texto de entrada tonta:

"6 de 99 fans enloquecidos"

Se volvería un grupo de 99 crazed partido.

El segundo patrón no coincidiría en absoluto, porque la palabra "enloquecido" no es la palabra "ventiladores".

Hmm. He aquí un último patrón que siempre debe hacer lo correcto, incluso con los textos de entrada tontas:

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

\d coincide con cualquier dígito ('0'-'9'). \D coincide con cualquier no-dígito.

Esto corresponderá con éxito cualquier cosa que sea remotamente no ambigua:

"6 de 99 ventiladores en toda la galaxia de fans"

El grupo partido será 99.

"6 de 99 fans enloquecidos"

El grupo partido quedan 99.

"6 de 99 41 fans"

No va a coincidir, porque había un segundo número de allí. Para obtener más información sobre las expresiones regulares de Python, puede leer variouswebpages. Para un rápido recordatorio, dentro del intérprete de Python, haces:

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

Cuando está "raspado" texto de una página web, es posible que a veces ir en contra de los códigos HTML. En general, las expresiones regulares no son una buena herramienta para ignorar el marcado HTML o XML (ver here); probablemente sea mejor utilizar Beautiful Soup para analizar el HTML y extraer el texto, seguido de una expresión regular para tomar el texto que realmente desea.

Espero que esto haya sido interesante y/o educativo.

+0

+1 por ancho y volumen – bernie

+0

interesante Y educativo - fantástico. muchas gracias. – oneAday

Cuestiones relacionadas