2014-07-24 2 views
1

Quand je fais cela:encodage :: UndefinedConversionError lors de l'utilisation open-uri

require 'open-uri' 
response = open('some-html-page-url-here') 
response.read 

Sur une certaine URL, je reçois l'erreur suivante (due à un mauvais encodage dans l'url de retour ?!):

Encoding::UndefinedConversionError: U+00A0 from UTF-8 to US-ASCII 

Un moyen de contourner cela pour toujours obtenir le contenu html?

Répondre

2

Dans l'introduction au module open-uri, les docs disent cela,

Il est possible d'ouvrir un http, https ou ftp URL comme si elle était un fichier

Et Si vous savez quelque chose sur la lecture de fichiers, vous devez connaître l'encodage du fichier que vous essayez de lire. Vous devez connaître l'encodage pour pouvoir dire à ruby ​​comment lire le fichier (c'est-à-dire le nombre d'octets (ou l'espace) que chaque personnage va occuper).

Dans le premier exemple de code dans la documentation, il y a ceci:

open("http://www.ruby-lang.org/en") {|f| 
    f.each_line {|line| p line} 
    p f.base_uri   # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/> 
    p f.content_type  # "text/html" 
    p f.charset   # "iso-8859-1" 
    p f.content_encoding # [] 
    p f.last_modified # Thu Dec 05 02:45:02 UTC 2002 
    } 

Donc, si vous ne connaissez pas le codage du « fichier » vous essayez de lire, vous pouvez obtenir l'encodage avec f.charset. Si ce codage est différent de votre default external encoding, vous obtiendrez probablement une erreur. Votre default external encoding est l'encodage que ruby ​​utilise pour lire des sources externes. Vous pouvez vérifier ce que l'encodage par défaut externe est réglé sur comme ça:

La valeur par défaut d'encodage externe est tiré de votre environnement ... Jetez un oeil :

$ echo $LC_CTYPE 
en_US.UTF-8 

ou

$ ruby -e 'puts Encoding.default_external.name' 
UTF-8 

http://graysoftinc.com/character-encodings/ruby-19s-three-default-encodings

Sur Mac OSX, je dois vraiment faire ce qui suit pour voir le codage externe par défaut:

$ echo $LANG 

Vous pouvez définir l'encodage par défaut externe avec la méthode Encoding.default_external=(), vous voudrez peut-être essayer quelque chose comme ceci:

open('some_url_here') do |f| 
    Encoding.default_external = f.charset 
    html = f.read 
    end 

Définition d'un objet IO binmode, comme vous l'avez fait, dit Ruby que l'encodage du fichier est BINARY (ou ASCII-8bit synonyme de confusion de rubis), ce qui signifie que vous dites ruby ​​que chaque personnage dans le fichier prend jusqu'à un octet. Dans votre cas, vous dites à ruby ​​de lire le caractère U + 00A0, dont la représentation UTF-8 prend deux octets 0xC2 0xA0, comme deux caractères au lieu d'un seul caractère, donc vous avez éliminé votre erreur, mais vous avez produit deux caractères indésirables au lieu du caractère original.

1

Effectuer un response.binmode avant que le response.read arrête l'erreur.

+0

merci, cela a résolu mon problème! –

0

eu le même problème, ajoutera ma solution ici:

Après avoir lu la documentation ouverte uri plus, il se trouve que vous pouvez définir l'encodage du io avant de lire en utilisant la méthode set_encoding, comme ceci:

result = open('some-page-uri') do |io| 
    io.set_encoding(Encoding.default_external) 
    io.read 
end 

Espérons que ça aide!

Questions connexes