Estoy escribiendo un rastreador en Ruby (1.9) que consume mucho HTML de muchos sitios aleatorios.
Al intentar extraer enlaces, decidí usar simplemente en .scan(/href="(.*?)"/i)
lugar de nokogiri / hpricot (mayor aceleración). El problema es que ahora recibo muchos " invalid byte sequence in UTF-8
" errores.
Por lo que entendí, la net/http
biblioteca no tiene opciones específicas de codificación y las cosas que vienen, básicamente, no están etiquetadas correctamente.
¿Cuál sería la mejor manera de trabajar realmente con esos datos entrantes? Intenté .encode
con el conjunto de opciones de reemplazo y no válidas, pero no tuve éxito hasta ahora ...
109
'U*'
deshace'C*'
?Respuestas:
En Ruby 1.9.3 es posible usar String.encode para "ignorar" las secuencias UTF-8 inválidas. Aquí hay un fragmento que funcionará tanto en 1.8 ( iconv ) como en 1.9 ( String # encode ):
o si tiene una entrada realmente problemática, puede hacer una doble conversión de UTF-8 a UTF-16 y volver a UTF-8:
fuente
file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '')
file_contents.encode!('UTF-8', 'UTF-16')
force_encoding
. Si ha leído un ISO8859-1 como un UTF-8 (y, por lo tanto, esa cadena contiene UTF-8 no válido), puede "reinterpretarlo" como ISO8859-1 con the_string.force_encoding ("ISO8859-1") y simplemente trabajar con esa cadena en su codificación real..encode('UTF-8')
es una operación y no se ejecutan verificaciones. Documentación de Ruby Core para codificar . Sin embargo, convertirlo a UTF-16 primero obliga a que se ejecuten todas las comprobaciones de secuencias de bytes no válidas, y los reemplazos se realizan según sea necesario.La respuesta aceptada ni la otra respuesta funcionan para mí. Encontré esta publicación que sugirió
Esto me solucionó el problema.
fuente
Mi solución actual es ejecutar:
Esto al menos eliminará las excepciones, que era mi principal problema.
fuente
valid_encoding?
que parece detectar cuando algo anda mal.val.unpack('C*').pack('U*') if !val.valid_encoding?
.\xB0
espalda en símbolos de grados. Incluso lavalid_encoding?
vuelve verdadera pero todavía comprobar si no es así y la tira a cabo los caracteres ofensivos usando la respuesta de Amir arriba:string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
. También había probado laforce_encoding
ruta pero falló.Prueba esto:
fuente
Te recomiendo que uses un analizador HTML. Solo encuentra el más rápido.
Analizar HTML no es tan fácil como parece.
Los navegadores analizan secuencias UTF-8 no válidas, en documentos HTML UTF-8, simplemente poniendo el símbolo " ". Entonces, una vez que se analiza la secuencia UTF-8 no válida en el HTML, el texto resultante es una cadena válida.
Incluso dentro de los valores de los atributos, debe decodificar entidades HTML como amp
Aquí hay una gran pregunta que resume por qué no puede analizar HTML de manera confiable con una expresión regular: RegEx coincide con las etiquetas abiertas, excepto las etiquetas autocontenidas XHTML
fuente
Esto parece funcionar:
fuente
fuente
Encontré cadenas, que tenían mezclas de inglés, ruso y algunos otros alfabetos, lo que causó una excepción. Solo necesito ruso e inglés, y esto actualmente me funciona:
fuente
Si bien la solución de Nakilon funciona, al menos en lo que respecta a superar el error, en mi caso, tuve este extraño carácter f-ed up que se originó en Microsoft Excel convertido a CSV que se registraba en ruby como (obtenga esto) cirílico K que en ruby era una K en negrita. Para arreglar esto, usé 'iso-8859-1' a saber.
CSV.parse(f, :encoding => "iso-8859-1")
, que convirtió mis extrañas K cirílicas deaky en una mucho más manejable/\xCA/
, que luego pude eliminar constring.gsub!(/\xCA/, '')
fuente
Antes de usar
scan
, asegúrese de que elContent-Type
encabezado de la página solicitada seatext/html
, ya que puede haber enlaces a cosas como imágenes que no están codificadas en UTF-8. La página también podría ser no html si seleccionóhref
algo como un<link>
elemento. La forma de comprobar esto varía según la biblioteca HTTP que esté utilizando. Luego, asegúrese de que el resultado sea solo ascii conString#ascii_only?
(no UTF-8 porque se supone que HTML solo usa ascii, las entidades se pueden usar de lo contrario). Si ambas pruebas pasan, es seguro de usarscan
.fuente
Si no le "importan" los datos, puede hacer algo como:
search_params = params[:search].valid_encoding? ? params[:search].gsub(/\W+/, '') : "nothing"
Solía
valid_encoding?
pasarlo. El mío es un campo de búsqueda, por lo que estaba encontrando la misma rareza una y otra vez, así que usé algo como: solo para que el sistema no se rompa. Dado que no controlo la experiencia del usuario para autovalidar antes de enviar esta información (como retroalimentación automática para decir "¡tonto!"), Puedo simplemente asimilarlo, eliminarlo y devolver resultados en blanco.fuente