2010-02-19 13 views
5

Tengo un poco de contenido de texto con una lista de URL contenidas en él.Extraer todas las direcciones URL dentro de una cadena en Ruby

Estoy tratando de tomar todas las direcciones URL y ponerlas en una matriz.

tengo este código

content = "Here is the list of URLs: http://www.google.com http://www.google.com/index.html" 

urls = content.scan(/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix) 

Estoy tratando de obtener los resultados finales sean:

['http://www.google.com', 'http://www.google.com/index.html'] 

El código anterior no parece estar funcionando correctamente. ¿Alguien sabe lo que estoy haciendo mal?

Gracias

Respuesta

5

Un enfoque diferente, desde el perfecto-es-el-enemigo-de-la-buena escuela de pensamiento:

urls = content.split(/\s+/).find_all { |u| u =~ /^https?:/ } 
+1

Le daré la simplicidad. Esto bien puede ser todo lo que se necesita. – Chowlett

+1

¡Me gradué de esa escuela! –

+0

Este enfoque omitirá muchas URL válidas y seleccionará incorrectamente muchas URL inválidas. – sferik

5

no han comprobado la sintaxis de la expresión regular, pero String.scan producirán una matriz, cada uno de cuyos miembros es una matriz de los grupos emparejados por su expresión regular. Por lo que cabe esperar que el resultado sea:

[['http', '.google.com'], ...]

que necesitará grupos /(?:stuff)/ que no encaja, si desea que el formato que has dado.

Editar (mirando regex): Además, su expresión regular se ve un poco mal. No desea los anclajes de inicio y fin (^ y $), ya que no espera que las coincidencias estén al inicio y al final de content. En segundo lugar, si su ([0-9]{1,5})? está tratando de capturar un número de puerto, creo que le faltan dos puntos para separar el dominio del puerto.

hacer otras modificaciones, después de jugar: Creo que quieres algo como esto:

content = "Here is the list of URLs: http://www.google.com http://www.google.com/index.html http://example.com:3000/foo" 
urls = content.scan(/(?:http|https):\/\/[a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(?:(?::[0-9]{1,5})?\/[^\s]*)?/ix) 
# => ["http://www.google.com", "http://www.google.com/index.html", "http://example.com:3000/foo"] 

... pero tenga en cuenta que no va a coincidir con las direcciones URL de direcciones IP puros (como http://127.0.0.1), a causa de el [a-z]{2,5} para el TLD.

42

Fácil:

ruby-1.9.2-p136 :006 > require 'uri' 
ruby-1.9.2-p136 :006 > URI.extract(content, ['http', 'https']) 
    => ["http://www.google.com", "http://www.google.com/index.html"] 
+0

por qué no está marcado como la respuesta correcta. grml –

+0

Esto debe marcarse como la respuesta. Mucho más elegante. – adeluccar

4

sólo por su interés:

Ruby tiene un módulo URI, que tiene una expresión regular implementada para hacer tales cosas:

require "uri" 

uris_you_want_to_grap = ['ftp','http','https','ftp','mailto','see'] 

html_string.scan(URI.regexp(uris_you_want_to_grap)) do |*matches| 
    urls << $& 
end 

Para obtener más información, visite la Ruby Ref: URI

Cuestiones relacionadas