2011-02-01 38 views
34

Estoy extrayendo texto de sitios remotos e intentando cargarlo en una aplicación Ruby 1.9/Rails 3 que usa utf-8 de manera predeterminada.Convertir caracteres no ASCII de ASCII-8BIT a UTF-8

Aquí es un ejemplo de un texto infractor:

miradas
Cancer Res; 71(3); 1-11. ©2011 AACR.\n 

Ese código de derechos de autor se expandió como este:

Cancer Res; 71(3); 1-11. \xC2\xA92011 AACR.\n 

Rubí me dice que la cadena está codificado como ASCII-8BIT y alimentar a mi La aplicación Rails me ofrece esto:

incompatible character encodings: ASCII-8BIT and UTF-8 

Puedo quitar el código de copyright usando este re Gex

str.gsub(/[\x00-\x7F]/n,'?') 

para producir este

Cancer Res; 71(3); 1-11. ??2011 AACR.\n 

Pero, ¿cómo puedo obtener un símbolo de copyright (y varios otros símbolos, como letras griegas) convierte en los mismos símbolos en UTF-8? Seguramente es posible ...

veo referencias a la utilización de force_encoding pero esto no funciona:

str.force_encoding('utf-8').encode 

Sé que existen muchas otras personas con problemas similares, pero todavía tengo que ver una solución que trabajos.

+1

¿Cómo saca el texto de los sitios remotos? Raspado de páginas? Muestre algunos ejemplos de código, incluido el cliente HTTP que está utilizando, y si está analizando las páginas con Nokogiri, Hpricot o ReXML. Este problema podría deberse a cómo está recuperando la página y a cómo está analizando la página. Una vez que sepamos que está extrayendo el contenido de una manera segura para los datos, podemos ayudarlo a convertir los datos entre los conjuntos de códigos. –

+0

Código simple real - open-uri y nokogiri - p. doc = Nokogiri :: XML (abrir (url)) luego doc.css (...). texto para extraer los bloques de texto relevantes –

+1

Mostrar código de muestra. ¿El archivo está recuperando HTML o XML? Nokogiri se preocupa por la diferencia al analizar. Además, proporcione algunas URL porque cada sitio en Internet es diferente. –

Respuesta

54

Esto funciona para mí:

#encoding: ASCII-8BIT 
str = "\xC2\xA92011 AACR" 
p str, str.encoding 
#=> "\xC2\xA92011 AACR" 
#=> #<Encoding:ASCII-8BIT> 

str.force_encoding('UTF-8') 
p str, str.encoding 
#=> "©2011 AACR" 
#=> #<Encoding:UTF-8> 
+0

Gracias! Esto fue tan útil. – Mike

+5

Esto podría provocar el error 'Secuencia de bytes no válida en UTF-8'. Le sugiero que use 'codificar ('UTF-8')' en su lugar. – jpemberthy

+0

Eso también me funciona, pero otras cadenas no. Por ejemplo: str = "Diario El d \ xEDa Bolivia" no se convertirá a "Diario El día Bolivia". –

6

que solía hacer esto por un guión que raspa páginas Windows griego-codificado, usando abierta uri, iconv y hpricot:

doc = open(DATA_URL) 
doc.rewind 
data = Hpricot(Iconv.conv('utf-8', "WINDOWS-1253", doc.readlines.join("\n"))) 

creo que era de ruby ​​1.8.7, no está seguro de cómo son las cosas con el rubí 1,9

+0

Gracias! Ninguna de las anteriores fueron manipulación "\ x96" para mí, seguiría siendo estallar. Iconv.conv ("UTF 8' , "Windows-1253", str) funcionaba perfecto. – spilliton

+0

también puede ser necesario para fijar el valor de transliterate' Iconv 'true. http://ruby-doc.org/stdlib-1.9.2/libdoc/iconv/rdoc /Iconv.html#method-i-transliterate-3D – wmarbut

23

hay dos posibilidades:

  1. Los datos de entrada ya son UTF-8, pero Ruby simplemente no lo sabe. Ese parece ser su caso, ya que "\ xC2 \ xA9" es válido UTF-8 para el símbolo de copyright. En ese caso, solo necesita decirle a Ruby que los datos ya son UTF-8 usando force_encoding.

    Por ejemplo, "\ xC2 \ xA9" .force_encoding ('ASCII-8BIT') recrearía el bit relevante de sus datos de entrada. Y "\ xC2 \ xA9" .force_encoding ('ASCII-8BIT'). Force_encoding ('UTF-8') demostraría que puede decirle a Ruby que es realmente UTF-8 y obtener el resultado deseado.

  2. Los datos de entrada están en otra codificación y necesita que Ruby lo transcodifique a UTF-8. En ese caso, tendría que decirle a Ruby cuál es la codificación actual (ASCII-8BIT es ruby-speak para binario, no es una codificación real), luego dígale a Ruby que lo transcodifique.

    Por ejemplo, supongamos que sus datos de entrada fueron ISO-8859-1. En esa codificación, el símbolo de copyright es simplemente "\ xA9". Esto generaría tal cantidad de datos: "\ xA9" .force_encoding ('ISO-8859-1') Y esto demostraría que puede obtener que Ruby transcodifique eso a UTF-8: "\ xA9" .force_encoding ('ISO -8859-1 ').encode ('UTF-8')

+0

que estaba recibiendo este tipo de error con los carriles + sql server configuración Resuelto "codificación: ISO-8859-1". en database.yml y el uso de "lating cadena" .encode ("UTF-8") –

+0

Perfecto. # 2 resolvió mi problema, tirando a través de Ruby/DBI desde Sql Server también. @Lucas Renan: Gracias por la información sobre rails/database.yml. Puedo agregar rieles más adelante para el sitio. – jetimms

Cuestiones relacionadas