2010-07-07 1 views
21

Для утомительных причин, связанных с Hpricot, мне нужно написать функцию, которая передается URL-адресом, и возвращает все содержимое страницы как одну строку.Извлечь содержимое URL как строку

Я рядом. Я знаю, что нужно использовать OpenURI, и это должно выглядеть примерно так:

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

Может кто-нибудь предложить, что мне нужно добавить?

ответ

16

Метод open проходит IO представление ресурса вашего блока, когда его доходность. Вы можете читать из него с помощью метода IO#read

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

спасибо и спасибо за объяснение того, что происходит за кулисами. – AP257

+0

Как бы вы обновили путь к относительным активам в вытащенном html? – saihgala

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

Смотрите также документацию IO class

50

Вы можете сделать то же самое без 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

Что недостаток использования открытого URI? – Watusimoto

+3

Да, это очень запутанно, что этот более сложный ответ имеет гораздо больше оборотов, чем другие. Я попытался найти причину самостоятельно и нашел [этот вопрос/ответ] (http://stackoverflow.com/a/16764302/199712), который в большинстве случаев рекомендует OpenURI поверх Net :: HTTP, что только делает вещи более запутанными , THANKS, OBAMA –

+4

open-uri внутренние исправления 'Kernel.open'. Здесь [статья] (http://sakurity.com/blog/2015/02/28/openuri.html) рассказывается о вещах, о которых следует знать при использовании open-uri. Я также столкнулся с конфликтом имен имен 'open' при использовании его вместе с другими библиотеками, такими как Bunny Gem (который также реализует' open') – EricC

-2

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

Как это отличается от решения, упомянутого ранее Teoulas? –

2

Чтобы сделать код немного понятнее, метод OpenURI open возвратит значение, возвращенное блоком, так что вы можете назначить open «s возвращаемого значения переменного. Например:

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

приятно, вот один лайнер для получить общедоступные IP-диапазоны Amazon EC2: 'ruby -r json -ropen-uri -e 'JSON.parse (открыть (" https://ip-ranges.amazonaws.com/ip-ranges.json ") {| io | io .read}) ["prefixes"]. each {| p | puts # {p ["ip_prefix"], если p ["service"] == "EC2"}; '' – akostadinov

+0

фиксированная опечатка в однострочном пространстве:' ruby -r json -r open-uri -e 'JSON.parse (открыть ("https://ip-ranges.amazonaws.com/ip-ranges.json ") {| io | io.read}) [" prefixes "]. each {| p | puts p [" ip_prefix "], если p [" service "] ==" EC2 "}; '' – Magnus

4

Я также был очень смущен, что использовать для повышения производительности и быстрых результатов. Я побежал тест для обоих, чтобы сделать его более ясным:

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 

Ее результат:

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

Я хотел бы сказать, что это зависит от того, что ваше требование и как вы хотите обработать ,

-1

Попробуйте следующие вместо:

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