Pregunta

Problema

Cuando la pantalla-raspado de una página web usando python, uno tiene que saber la codificación de caracteres de la página. Si usted consigue la codificación de caracteres mal que la salida será en mal estado.

La gente suele utilizar de forma rudimentaria técnica para detectar la codificación.Utilizan el juego de caracteres del encabezado o el conjunto de caracteres definidos en la etiqueta meta o utilizan un codificación detector de (que no se preocupa de las etiquetas meta o cabeceras).Mediante el uso de sólo una de estas técnicas, a veces no se obtiene el mismo resultado como lo haría en un navegador.

Los navegadores hacen de esta manera:

  • Etiquetas Meta siempre tiene prioridad (o de definición xml)
  • Codificación definida en el encabezado se utiliza cuando no hay ningún conjunto de caracteres definidos en una etiqueta meta
  • Si la codificación no está definido del todo, que es el tiempo para la detección de codificación.

(Bueno...al menos esa es la forma en que creo que la mayoría de los navegadores de hacerlo.La documentación es muy escasa.)

Lo que estoy buscando es una biblioteca que puede decidir el conjunto de caracteres de una página como lo haría un navegador. Estoy seguro de que no soy el primero que necesita una solución adecuada a este problema.

Solución (No he probado todavía...)

De acuerdo a Hermosa Sopa de documentación del.

La Sopa de hermosa intenta las siguientes codificaciones, en orden de prioridad, para convertir el documento en Unicode:

  • Una codificación que pase como el fromEncoding argumento a la sopa constructor.
  • Una codificación descubierto en el propio documento:por ejemplo, en una declaración XML o (documentos HTML) http-equiv etiqueta META.Si la Sopa de Hermosa se encuentra este tipo de codificación dentro del documento, se analiza el documento de nuevo desde el principio y le da a la nueva codificación de un intento.La única excepción es si usted especifica explícitamente una codificación, y que la codificación efectivamente trabajadas:a continuación, se hará caso omiso de cualquier codificación se encuentra en el documento.
  • Una codificación resopló mirando los primeros bytes del archivo.Si se detecta una codificación en esta etapa, va a ser uno de los UTF-* codificaciones, EBCDIC, ASCII.
  • Un la codificación de los huele el chardet la biblioteca, si lo tienes instalado.
  • UTF-8
  • Windows-1252
¿Fue útil?

Solución

Me gustaría utilizar html5lib para esto.

Otros consejos

Cuando se descarga un archivo con urllib o urllib2, usted puede averiguar si un conjunto de caracteres del encabezado se transmitió:

fp = urllib2.urlopen(request)
charset = fp.headers.getparam('charset')

Usted puede utilizar BeautifulSoup para localizar un elemento meta en el HTML:

soup = BeatifulSoup.BeautifulSoup(data)
meta = soup.findAll('meta', {'http-equiv':lambda v:v.lower()=='content-type'})

Si ninguno está disponible, los navegadores suelen caer de nuevo a configuración de usuario, combinado con auto-detección.Como rajax propone, puede utilizar el chardet módulo.Si usted tiene configuración de usuario disponible que indica que la página debe ser Chino (por ejemplo), usted puede ser capaz de hacerlo mejor.

El uso de la Universal De Codificación Detector De:

>>> import chardet
>>> chardet.detect(urlread("http://google.cn/"))
{'encoding': 'GB2312', 'confidence': 0.99}

La otra opción sería usar wget:

  import os
  h = os.popen('wget -q -O foo1.txt http://foo.html')
  h.close()
  s = open('foo1.txt').read()

Le parece que necesita un híbrido de las respuestas que se presentan:

  1. Buscar la página con urllib
  2. Encontrar <meta> etiquetas utilizando hermosa sopa u otro método
  3. Si no hay etiquetas meta de existir, comprobar las cabeceras devueltas por urllib
  4. Si es que aún no te dé una respuesta, use el universal de codificación detector.

Honestamente no creo que vas a encontrar nada mejor que eso.

De hecho, si usted lee más en la sección vinculada a los comentarios en la otra respuesta, que es lo que el autor de detector de la biblioteca de los defensores.

Si usted cree que el FAQ, esto es lo que los navegadores (como se pide en la pregunta original) como el detector es un puerto de firefox oler código.

Scrapy de descarga de una página y detecta una codificación correcta para ella, a diferencia de las solicitudes.get(url).texto o urlopen.Para ello se trata de seguir en el navegador, tales como las reglas - este es el mejor que uno puede hacer, porque los propietarios de sitios web tienen incentivos para hacer que sus sitios web funcionan en un navegador.Scrapy necesita tomar encabezados HTTP, <meta> etiquetas, lista de materiales y marcas de las diferencias en la codificación de los nombres en cuenta.

Basado en el contenido de adivinanzas (chardet, UnicodeDammit) por sí sola no es una solución correcta, como se puede fallar;debe ser utilizado solamente como un último recurso cuando encabezados o <meta> o BOM marcas no están disponibles o no proporciona ninguna información.

Usted no tiene que usar Scrapy para obtener su detección de codificación de funciones;son liberados (entre otras cosas) en una biblioteca independiente llamado w3lib: https://github.com/scrapy/w3lib.

Para obtener la codificación de la página de unicode y el uso del cuerpo w3lib.de la codificación.html_to_unicode la función, con un contenido basado en adivinar de reserva:

import chardet
from w3lib.encoding import html_to_unicode

def _guess_encoding(data):
    return chardet.detect(data).get('encoding')

detected_encoding, html_content_unicode = html_to_unicode(
    content_type_header,
    html_content_bytes,
    default_encoding='utf8', 
    auto_detect_fun=_guess_encoding,
)

en lugar de tratar de obtener una página, a continuación, averiguar el charset el navegador, por qué no sólo tiene que utilizar un navegador para ir a buscar la página y comprobar qué juego de caracteres que utiliza..

from win32com.client import DispatchWithEvents
import threading


stopEvent=threading.Event()

class EventHandler(object):
    def OnDownloadBegin(self):
        pass

def waitUntilReady(ie):
    """
    copypasted from
    http://mail.python.org/pipermail/python-win32/2004-June/002040.html
    """
    if ie.ReadyState!=4:
        while 1:
            print "waiting"
            pythoncom.PumpWaitingMessages()
            stopEvent.wait(.2)
            if stopEvent.isSet() or ie.ReadyState==4:
                stopEvent.clear()
                break;

ie = DispatchWithEvents("InternetExplorer.Application", EventHandler)
ie.Visible = 0
ie.Navigate('http://kskky.info')
waitUntilReady(ie)
d = ie.Document
print d.CharSet

BeautifulSoup dosis de este con UnicodeDammit : Unicode, Maldita Sea

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top