Parsear página web y extraer datos.

FaLLeN

Hola Mediavideros!
Tengo que extraer unos datos de una serie de páginas web. Entre ellos, varios links y demás textos.

Me han comentado que con expresiones regulares puede funcionar bien la cosa, pero otros dicen que pueden ir lentas(?)

Os pongo un ejemplo de lo que querría hacer.

  • En la web de destino, sacar X href específicos.
  • Cerca de ese enlace, en el código, hay un texto que tambíen quiero extraer.

#2 python es demasiado dificil para mi, que no soy programador...

allmy

Scripteando en python es bastante sencillo. Si te interesa mírate la referencia de como trabajar con strings. Si quieres más dime y te explico.

#4 http://docs.python.org/howto/webservers.html

2 respuestas
B

pues ya me explicarás como parsear html sin expresiones regulares

2 respuestas
FaLLeN

#2 Puedo usar python desde mi web que está programada en php?

#3 Puede ser que leyera algo relacionado con substr o algo asi?

1 respuesta
LOc0

http://www.mediavida.com/foro/9/obtener-numero-de-una-web-441564/2

Salu2 ;)

Puni

Recuerdo que una vez hice un crawler en Java. Después de los millones de quebraderos de cabeza que me dió leer el html debido a que los navegadores tragan con todo, vease hrefs sin comillas, comillas simples, sin espacios entre atributos de la etiqueta, saltos de linea a mitad de uris etc, decidí que si lo volvía a hacer primero pasar el XHTML Validator, si no está bien formado: a tomar por saco. Y con los que estén bien: usar un parser XML y listo.

He estado ojeando el código y mi madre, si eres un genio y un dios de las expresiones regulares probablemente hagas magia. Yo fui muy poco a poco y a base de substrings y replaces hasta se entiende el código pero vamos. Mi consejo sigue siendo el mismo: valida y parsea.

FaLLeN

Yo me vuelvo loco con las expresiones regulares estas...

"/<a.{1,}href=\"?([a-zA-Z:\.\/]*)\"?.{0,}>(.*)<\/a>/i"

con esa estoy sacando los href, pero como lo pondría si el href llevara algo fijo despues:

href="estosiempreesfijo/aquiestocambia"

Luego un texto que tambien tiene parte fija y parte que cambia:

TEXTOFIJO CAMBIA

EnZo

Pero quieres capturar todo (estosiempreesfijo/aquiestocambia)

o solo "aquiestocambia" ?

PD: Las ExpReg tienen su miga, así que es normal que te vuelvas loco al principio.

1 respuesta
FaLLeN

#8 Quiero que reconozca (estosiempreesfijo/aquiestocambia) para capturar "aquiestocambia"

Otra cuestión es: Solo me reconoce la primera, o me coge todas las coincidencias de la web?

1 respuesta
EnZo

#9 Prueba esto

/<a.{1,}href=\"?http:\/\/www\.direccionweb\.com\/([^"]*)\"?.{0,}>(.*)<\/a>/i
1 respuesta
FaLLeN

#10

Hasta ahi comprendo. Las dudas que me vienen ahora son:

  • Una vez que tengo la cadena extraida, puedo modificarla con un substr o algo asi no?
  • Esto solo me captura la primera coincidencia. si luego cargo $coincidencia[1] ya no me lee el siguiente. Hay alguna manera de que lea un determinado numero de veces?
1 respuesta
PiradoIV

Hay bibliotecas PHP por ahí para hacer esto mil veces más fácil, con selectores tipo jQuery

// Create DOM from URL or file
$html = file_get_html('http://www.google.com/');

// Find all images 
foreach($html->find('img') as $element) 
       echo $element->src . '<br>';

// Find all links 
foreach($html->find('a') as $element) 
       echo $element->href . '<br>';

http://simplehtmldom.sourceforge.net/

Ninja-edit: Vamos, realmente merece la pena usar una biblioteca de estas ... y ya si necesitas un rendimiento extremo, prueba a hacerte tus propias expresiones regulares específicas, pero mientras funcione más o menos como esperas...

1 respuesta
EnZo

#11 usa preg_match_all en vez de preg_match. Y una vez ejecutada usa print_r($turesultado);

Para que veas que valores te devuelve.

1 respuesta
FaLLeN

#12 Le voy a echar un vistazo a ver si gana en rendimiento.

#13 Ahora si me muestra todos los resultados capturados y con $turesultado[X][X] puedo elegir cual me quedo. Perfecto entonces.

Teniendo en cuenta que la web que quiero consultar es pesada, me conviene hacer el file_get_contents cada vez o como suele hacerse?

1 respuesta
EnZo

#14 Tienes que ejecutar el script cada vez que un usuario entre? O lo haces tú de forma interna periodicamente?

Si es la primera opcion, yo lo haria con fopen. Porque fopen vas descargando el contenido de la web poco a poco. Entonces una vez que ya tienes todo el contenido que necesitas scrapeado cierras el resource. Esta tecnica consume mas cpu pero ahorras mucho mas en ancho de banda y a la larga compensa.

1 respuesta
FaLLeN

#15 tal que asi?

$web=fopen("http://www.webdestino.com/");
PiradoIV

y lo suyo sería usar alguna caché, para no descargarte la misma web varias veces

EnZo

http://www.php.net/manual/es/function.fread.php

Mirate: Ejemplo #3 Ejemplos de lectura remota con fread()

De todas formas con file_get... te va a ir bien. Cuando tengas muchisisimas visitas entonces ya optimizarás más. Como estás aprendiendo hazlo como practica si quieres pero la primera opcion te va a ir bien. Además aunque el codigo de la web sea tocho las regexp tienen un rendimiento muy alto.

Y como dice PiradoIV si la web no cambia mucho... usa cache, o scrapea tu una vez al dia...

1 respuesta
FaLLeN

Pues gracias! A ver si sigo adelante y no muero en el intento :D

B

#18 repito, como sacas las url,etc sin PARSEAR EL CONTENIDO con expresiones regulares?

2 respuestas
LOc0

#20

Con una biblioteca que por debajo usa...

spoiler

Salu2 ;)

1 respuesta
EnZo

#20 #21 xD

Usuarios habituales