2009-07-30 12 views
7

Mam aplikacji Sinatra (http://analyzethis.espace-technologies.com), który wykonuje następująceJak przekonwertować odpowiedź Net :: HTTP na określone kodowanie w Rubim 1.9.1?

  1. Odzyskaj stronę HTML (przez net/HTTP)
  2. utworzyć dokument Nokogiri z response.body
  3. wyodrębnić pewne informacje i wysyłać to z powrotem w odpowiedzi. Odpowiedź powinna być zakodowana w kodowaniu UTF-

Tak więc doszedłem do problemu, próbując czytać strony, które używają kodowań Windows-1256, takich jak www.filfan.com lub www.masrawy.com.

Problem polega na tym, że konwersja kodowania nie jest poprawna, ale nie są zgłaszane żadne błędy.

Siatka/http response.body.encoding daje ASCII-8bit, które nie mogą być zamienione na UTF-8

Jeśli robię Nokogiri :: HTML (response.body) i korzystać z selektorów CSS, aby uzyskać pewność, treść ze strony - powiedz na przykład treść tagu tytułowego - otrzymuję ciąg znaków, który po wywołaniu string.encoding zwraca WINDOWS-1256. Używam string.encode ("utf-8") i wysyłam odpowiedź, ale odpowiedź jest nieprawidłowa.

Jakieś sugestie lub pomysły na temat tego, co jest nie tak w moim podejściu?

Odpowiedz

3

znalazłem następujący kod działa dla mnie teraz

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

Działa świetnie! –

20

Ponieważ Net :: HTTP nie obsługuje kodowania poprawnie. Zobacz http://bugs.ruby-lang.org/issues/2567

Można analizować składnię response['content-type'], która zawiera zestaw znaków zamiast analizowania całych response.body.

Następnie użyj force_encoding(), aby ustawić właściwe kodowanie.

response.body.force_encoding("UTF-8") jeśli witryna jest wyświetlana w UTF-8.

+0

Mimo że to rozwiązanie działa, problem ten dotyczy tylko niektórych witryn. Być może kiedy Content-Type zawiera "application/json", to koduje w UTF-8 ...? Według http://stackoverflow.com/questions/9254891/what-does-content-type-application-json-charset-utf-8-really-mean, application/json oznacza kodowanie UTF-8. –

+1

Następnym logicznym krokiem będzie wywołanie kodu .encode! ('UTF-8') na wynikowym łańcuchu, a następnie wykonanie rzeczywistego przetwarzania –

+0

@DmitryVyal Uratowałeś mojego współtowarzysza dnia – JustMichael

Powiązane problemy