2010-05-03 1 views
7

Я хочу, чтобы получить данные с этой страницы:Использование OpenUri, как я могу получить содержимое страницы перенаправления?

http://www.canadapost.ca/cpotools/apps/track/personal/findByTrackNumber?trackingNumber=0656887000494793 

Но что страница вперед к:

http://www.canadapost.ca/cpotools/apps/track/personal/findByTrackNumber?execution=eXs1 

Так что, когда я использую open, от OpenUri, чтобы попытаться и выборки данных, он бросает a RuntimeError ошибка HTTP redirection loop:

Я не уверен, как получить эти данные после перенаправления и выкидывания этой ошибки.

+0

Является ли open-uri обязательным, вы также были бы довольны другой рубиновой технологией? –

+0

Еще одна рубиновая техника определенно хороша, если это необходимо. – Shpigford

+0

'open-uri' уже обрабатывает перенаправление. Он просто ошибается, когда сталкивается с переадресацией – lulalala

ответ

22

Вам нужен такой инструмент, как Mechanize. Из описания:

Библиотека Mechanize используется для , что позволяет автоматизировать взаимодействие с веб-сайтами. Механизм автоматически сохраняет и отправляет файлы cookie, следует за перенаправлениями, может следовать ссылкам и отправлять формы. Форма поля могут быть заполнены и отправлены. Mechanize также отслеживает сайты, которые вы посетили как историю .

Это именно то, что вам нужно. Так,

sudo gem install mechanize 

затем

require 'mechanize' 
agent = WWW::Mechanize.new 
page = agent.get "http://www.canadapost.ca/cpotools/apps/track/personal/findByTrackNumber trackingNumber=0656887000494793" 

page.content # Get the resulting page as a string 
page.body # Get the body content of the resulting page as a string 
page.search(".somecss") # Search for specific elements by XPath/CSS using nokogiri 

и вы готовы к рок-н-ролл.

1

Сайт, похоже, выполняет некоторую логику перенаправления с сеансами. Если вы не отправляете файлы cookie сеанса, которые они отправляют по первому запросу, вы попадете в цикл перенаправления. ИМХО - это дерьмовая реализация с их стороны.

Тем не менее, я попытался передать им файлы cookie, но я не получил его на работу, поэтому я не могу быть абсолютно уверен, что это все, что происходит здесь.

+0

Правильно, вот что я прошу ... потому что это перенаправление, как мне получить данные со страницы, на которую она перенаправляется? – Shpigford

+0

Я перефразировал свой ответ, чтобы сделать мой вопрос более ясным. Я не просто сказал, что это перенаправление, я также объяснил, почему вы оказались в цикле, надеюсь, теперь должно быть ясно. – Theo

1

В то время как механизация - прекрасный инструмент, я предпочитаю «готовить» свою собственную вещь.

Если вы серьезно относитесь к разбору, вы можете взглянуть на этот код. Он служит для обхода тысяч сайтов на международном уровне каждый день, и, насколько я исследовал и настраивал, нет более стабильного подхода к этому, что также позволяет вам в большей степени настраивать ваши потребности.

require "open-uri" 
require "zlib" 
require "nokogiri" 
require "sanitize" 
require "htmlentities" 
require "readability" 

def crawl(url_address) 
self.errors = Array.new 
begin 
    begin 
    url_address = URI.parse(url_address) 
    rescue URI::InvalidURIError 
    url_address = URI.decode(url_address) 
    url_address = URI.encode(url_address) 
    url_address = URI.parse(url_address) 
    end 
    url_address.normalize! 
    stream = "" 
    timeout(8) { stream = url_address.open(SHINSO_HEADERS) } 
    if stream.size > 0 
    url_crawled = URI.parse(stream.base_uri.to_s) 
    else 
    self.errors << "Server said status 200 OK but document file is zero bytes." 
    return 
    end 
rescue Exception => exception 
    self.errors << exception 
    return 
end 
# extract information before html parsing 
self.url_posted  = url_address.to_s 
self.url_parsed  = url_crawled.to_s 
self.url_host   = url_crawled.host 
self.status   = stream.status 
self.content_type  = stream.content_type 
self.content_encoding = stream.content_encoding 
self.charset   = stream.charset 
if stream.content_encoding.include?('gzip') 
    document = Zlib::GzipReader.new(stream).read 
elsif stream.content_encoding.include?('deflate') 
    document = Zlib::Deflate.new().deflate(stream).read 
#elsif stream.content_encoding.include?('x-gzip') or 
#elsif stream.content_encoding.include?('compress') 
else 
    document = stream.read 
end 
self.charset_guess = CharGuess.guess(document) 
if not self.charset_guess.blank? and (not self.charset_guess.downcase == 'utf-8' or not self.charset_guess.downcase == 'utf8') 
    document = Iconv.iconv("UTF-8", self.charset_guess, document).to_s 
end 
document = Nokogiri::HTML.parse(document,nil,"utf8") 
document.xpath('//script').remove 
document.xpath('//SCRIPT').remove 
for item in document.xpath('//*[translate(@src, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")]') 
    item.set_attribute('src',make_absolute_address(item['src'])) 
end 
document = document.to_s.gsub(/<!--(.|\s)*?-->/,'') 
self.content = Nokogiri::HTML.parse(document,nil,"utf8") 
end