2009-07-30 5 views
7

J'ai une application Sinatra (http://analyzethis.espace-technologies.com) qui effectue les opérations suivantesComment convertir une réponse Net :: HTTP à un certain codage dans Ruby 1.9.1?

  1. Récupérer une page HTML (via net/http)
  2. Créez un document Nokogiri de la response.body
  3. Extrait quelques informations et envoyer retour dans la réponse. La réponse doit être codée en UTF-8

J'ai donc rencontré le problème en essayant de lire les sites qui utilisent des encodages Windows-1256 comme www.filfan.com ou www.masrawy.com.

Le problème est le résultat de la conversion de codage n'est pas correct si aucune erreur n'est levée.

Le filet/http response.body.encoding donne ASCII 8BIT qui ne peut être converti en UTF-8

Si je Nokogiri :: HTML (response.body) et utiliser les sélecteurs CSS pour obtenir certains contenu de la page - dire le contenu de la balise de titre par exemple - je reçois une chaîne qui, quand j'appelle string.encoding renvoie WINDOWS-1256. J'utilise string.encode ("utf-8") et envoie la réponse en utilisant cela mais encore une fois la réponse n'est pas correcte.

Des suggestions ou des idées sur ce qui ne va pas dans mon approche?

Répondre

3

Je trouve le code suivant travail pour moi maintenant

def document 
    if @document.nil? && response 
    @document = if document_encoding 
        Nokogiri::HTML(response.body.force_encoding(document_encoding).encode('utf-8'),nil, 'utf-8') 
       else 
        Nokogiri::HTML(response.body) 
       end 
    end 
    @document 
end 

def document_encoding 
    return @document_encoding if @document_encoding 
    response.type_params.each_pair do |k,v| 
    @document_encoding = v.upcase if k =~ /charset/i 
    end 
    unless @document_encoding 
    #document.css("meta[http-equiv=Content-Type]").each do |n| 
    # attr = n.get_attribute("content") 
    # @document_encoding = attr.slice(/charset=[a-z1-9\-_]+/i).split("=")[1].upcase if attr 
    #end 
    @document_encoding = response.body =~ /<meta[^>]*HTTP-EQUIV=["']Content-Type["'][^>]*content=["'](.*)["']/i && $1 =~ /charset=(.+)/i && $1.upcase 
    end 
    @document_encoding 
end 
+0

Cela fonctionne très bien! –

20

Parce que Net :: HTTP ne gère pas correctement coder. Voir http://bugs.ruby-lang.org/issues/2567

Vous pouvez analyser response['content-type'] qui contient le jeu de caractères au lieu de l'analyse complète response.body.

Ensuite, utilisez force_encoding() pour définir le codage correct.

response.body.force_encoding("UTF-8") si le site est servi en UTF-8.

+0

Bien que cette solution fonctionne, ce problème ne m'est arrivé que pour certains sites. Peut-être que quand le Content-Type inclut "application/json", alors il encodera en UTF-8 ...? Selon http://stackoverflow.com/questions/9254891/what-does-content-type-application-json-charset-utf-8-really-mean, application/json implique UTF-8. –

+1

La prochaine étape logique serait d'appeler .encode! ('UTF-8') sur la chaîne résultante, puis de faire le traitement réel –

+0

@DmitryVyal Vous avez enregistré mon compagnon de jour – JustMichael

Questions connexes