2010-07-07 12 views
21

Por tediosas razones para hacer con Hpricot, necesito escribir una función a la que se le pasa una URL, y devuelve todo el contenido de la página como una sola cadena.Recuperar el contenido de la URL como cadena

Estoy cerca. Sé que necesito para usar OpenURI, y debería ser algo como esto:

require 'open-uri' 
open(url) { 
    # do something mysterious here to get page_string 
} 
puts page_string 

Puede alguien sugerir lo que tengo que añadir?

Respuesta

16

El método open pasa un IO representación del recurso a su bloque cuando se rendimientos Puede leer de él utilizando el método de IO#read

open([mode [, perm]] [, options]) [{|io| ... }] 
open(path) { |io| data = io.read } 
+0

¡Gracias! y gracias por explicar lo que está sucediendo detrás de las escenas. – AP257

+0

¿Cómo actualizaría la ruta a los activos relativos en html extraído? – saihgala

11
require 'open-uri' 
open(url) do |f| 
    page_string = f.read 
end 

Véase también la documentación de IO class

50

Puede hacer lo mismo sin OpenURI:

require 'net/http' 
require 'uri' 

def open(url) 
    Net::HTTP.get(URI.parse(url)) 
end 

page_content = open('http://www.google.com') 
puts page_content 
+11

¿Cuál es la desventaja de usar open-uri? – Watusimoto

+3

Sí, es super confuso que esta respuesta más complicada tenga mucho más votos ascendentes que los demás. Intenté buscar una razón yo mismo y encontré [esta pregunta/respuesta] (http://stackoverflow.com/a/16764302/199712) que parece recomendar OpenURI sobre Net :: HTTP en la mayoría de los casos, lo que hace que las cosas sean más confusas . GRACIAS, OBAMA –

+4

open-uri internamente parches 'Kernel.open'. Aquí hay un [artículo] (http://sakurity.com/blog/2015/02/28/openuri.html) hablando sobre cosas de las que uno debería estar enterado al usar open-uri. También me he encontrado con el método de nomenclatura de conflictos 'abierto' cuando se usa junto con otras bibliotecas como bunny gem (que también implementa' open') – EricC

-2

require 'open-uri' 
open(url) {|f| #url must specify the protocol 
str = f.read() 
} 
+1

¿Cómo se diferencia esto de la solución mencionada anteriormente por Teoulas? –

2

Para hacer que el código un poco más claro, el método OpenURI open devolverá el valor devuelto por el bloque, lo que puede asignar open 's valor devuelto a la variable. Por ejemplo:

xml_text = open(url) { |io| io.read } 
+0

Bien, aquí hay un trazador de líneas a Obtenga los rangos de IP públicos de Amazon EC2: 'ruby -r json -ropen-uri -e 'JSON.parse (open (" https://ip-ranges.amazonaws.com/ip-ranges.json ") {| io | io .read}) ["prefixes"]. each {| p | puts # {p ["ip_prefix"] if p ["service"] == "EC2"}; '' – akostadinov

+0

error de escritura fijo en el one-liner: ' ruby -r json -r open-uri -e 'JSON.parse (abrir ("https://ip-ranges.amazonaws.com/ip-ranges.json ") {| io | io.read}) [" prefixes "]. each {| p | puts p [" ip_prefix "] si p [" servicio "] ==" EC2 "}; '' – Magnus

4

También estaba muy confundido acerca de qué usar para un mejor rendimiento y resultados rápidos. Me encontré con un punto de referencia para los dos para que sea más claro:

require 'benchmark' 
require 'net/http' 
require "uri" 
require 'open-uri' 

url = "http://www.google.com" 
Benchmark.bm do |x| 
    x.report("net-http:") { content = Net::HTTP.get_response(URI.parse(url)).body if url } 
    x.report("open-uri:") { open(url){|f| content = f.read } if url } 
end 

Su resultado es:

   user  system  total  real 
net-http: 0.000000 0.000000 0.000000 ( 0.097779) 
open-uri: 0.030000 0.010000 0.040000 ( 0.864526) 

me gustaría decir que depende de lo que su exigencia es y cómo desea procesar .

-1

intente lo siguiente en su lugar:

require 'open-uri' 
content = URI(your_url).read 
Cuestiones relacionadas