2010-05-03 10 views
7

Je veux obtenir des données de cette page:En utilisant OpenUri, comment puis-je obtenir le contenu d'une page de redirection?

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

mais cette page avant de:

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

Alors, quand je l'utilise open, de openURI, pour essayer de récupérer les données, il jette une erreur RuntimeError dire HTTP redirection loop:

Je ne suis pas vraiment sûr comment obtenir ces données après qu'il redirige et lève cette erreur.

+0

Est-ce que l'open-uri est obligatoire et seriez-vous satisfait d'une autre technologie de rubis? –

+0

Une autre technologie ruby ​​est vraiment bien si c'est nécessaire. – Shpigford

+0

'open-uri' gère déjà la redirection. Il se trompe en rencontrant redirection-loop – lulalala

Répondre

22

Vous avez besoin d'un outil comme Mechanize. De sa description:

La bibliothèque Mechanize est utilisée pour l'automatisation de l'interaction avec les sites Web. Mécaniser automatiquement les magasins et envoie des cookies, suit les redirections, peut suivre les liens, et soumettre des formes. Les champs peuvent être remplis et soumis. Mechanize garde aussi trace des sites que vous avez visités en tant qu'historique .

exactement ce dont vous avez besoin. Ainsi,

sudo gem install mechanize 

puis

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 

et vous êtes prêt pour le rock 'n' roll.

1

Le site semble faire partie de la logique de redirection avec des sessions. Si vous ne renvoyez pas les cookies de session qu'ils envoient à la première requête, vous finirez dans une boucle de redirection. À mon humble avis, c'est une mise en œuvre merdique de leur part. Cependant, j'ai essayé de leur transmettre les cookies, mais je n'ai pas réussi à les faire fonctionner, donc je ne peux pas être complètement sûr que c'est tout ce qui se passe ici.

+0

Bon, c'est ce que je demande ... parce que c'est une redirection, comment puis-je obtenir les données de la page vers laquelle il redirige? – Shpigford

+0

J'ai reformulé ma réponse pour clarifier mon propos. Je ne disais pas que c'était une redirection, j'ai aussi expliqué pourquoi vous vous êtes retrouvé dans une boucle, j'espère que cela devrait être clair maintenant. – Theo

1

Alors que la mécanisation est un outil merveilleux, je préfère cuisiner ma propre chose.

Si vous êtes sérieux au sujet de l'analyse, vous pouvez consulter ce code. Il sert à explorer des milliers de sites au niveau international tous les jours et dans la mesure où j'ai fait des recherches et peaufiné il n'y a pas une approche plus stable à cela qui vous permet également de personnaliser hautement plus tard vos besoins.

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