2012-04-24 25 views
9

En mi sitio web las personas pueden publicar noticias y bastantes editores usan palabras MS y herramientas similares para escribir el texto y luego copiar & pegar en el editor de mi sitio (simple textarea, no WYSIWYG etc.).Python: Reemplazar comillas tipográficas, guiones, etc. con sus homólogos de ascii

Estos textos suelen contener comillas "agradables" en lugar de ascii simples ("). También a veces contienen esos guiones más largos como en lugar de -.

Ahora quiero reemplazar todos esos caracteres con sus contrapartes de ASCII. Sin embargo, no quiero eliminar diéresis y otro carácter no ascii. También preferiría usar una solución adecuada que no implique crear un dict de mapeo para todos esos personajes.

Todas mis cadenas son objetos Unicode.

+0

¿Por qué no usar solo unicode? (Sé que usted sabe que es una opción) También, hay una lista unicode oficial de caracteres confusibles que pueden ayudar si tiene que hacer su propio. – Marcin

+0

Yo uso UTF8/unicode. Algunas personas usan el área de texto para escribir su contenido, así que ahora tengo una combinación de ambos estilos de cotización dependiendo de quién escribió algo que es bastante feo. – ThiefMaster

+0

¿Qué tal un formateador de rebajas para normalizar esas cosas? – Marcin

Respuesta

-2

Esta herramienta va a normalizar la puntuacion en rebajas: http://johnmacfarlane.net/pandoc/README.html

-S, --smart producir una salida tipográficamente correcta, la conversión de comillas rectas con comillas tipográficas, --- EM-guiones, - a ES- guiones, y ... a elipsis. Los espacios sin separación se insertan después de ciertas abreviaturas , como "Sr." (Nota: Esta opción solo es significativa cuando el formato de entrada es rebaja o textil. Se selecciona automáticamente cuando el formato de entrada es textil o el formato de salida es látex o contexto.)

Es Haskell, así que tendrías que descubrir la interfaz.

+1

Preferiría una solución de python y al revés ... – ThiefMaster

0

Puede usar el método str.translate() (http://docs.python.org/library/stdtypes.html#str.translate). Sin embargo, lea el documento relacionado con Unicode: la tabla de traducción tiene otra forma: número ordinal unicode -> cadena unicode (generalmente char) o None.

Bueno, pero requiere el dict. Tienes que capturar los reemplazos de todos modos. ¿Cómo quieres hacer eso sin ninguna tabla o matriz? Puede usar str.replace() para los caracteres individuales, pero esto sería ineficiente.

+0

Tenía la esperanza de que haya alguna forma inteligente de traducir solo caracteres que no sean letras. – ThiefMaster

0

¿Qué tal esto? Primero crea la tabla de traducción, pero sinceramente, no creo que puedas hacer esto sin ella.

transl_table = dict([ (ord(x), ord(y)) for x,y in zip(u"‘’´“”–-", u"'''\"\"--") ]) 

with open("a.txt", "w", encoding = "utf-8") as f_out : 
    a_str = u" ´funny single quotes´ long–-and–-short dashes ‘nice single quotes’ “nice double quotes” " 
    print(" a_str = " + a_str, file = f_out) 

    fixed_str = a_str.translate(transl_table) 
    print(" fixed_str = " + fixed_str, file = f_out ) 

yo no era capaz de ejecutar esta impresión a una consola (en Windows) así que tuve que escribir en el archivo txt.
La salida en el archivo a.txt se ve de la siguiente manera:

a_str ='funny sola quotes' larga - y - “agradable” comillas dobles trazos cortos 'agradables individuales citas' fixed_str = 'divertido comillas simples 'buenas' comillas dobles largos - - como tampoco de guiones cortos 'agradables comillas simples'

por cierto, el código anterior funciona en Python 3. Si se necesitan para Python 2, podría necesita algunas correcciones debido a la diferencia en el manejo de cadenas Unicode en las dos versiones del lenguaje

0

Puede construir sobre el paquete unidecode.

Esto es bastante lento, ya que estamos normalizando todo el Unicode primero a la forma combinada, luego tratamos de ver en qué lo convierte unidecode. Si hacemos coincidir una letra latina, entonces realmente usamos el carácter NFC original. Si no, entonces cedemos lo que haya sugerido unidecode desalentador. Esto deja letras acentuadas solo, pero convertirá todo lo demás.

import unidecode 
import unicodedata 
import re 

def char_filter(string): 
    latin = re.compile('[a-zA-Z]+') 
    for char in unicodedata.normalize('NFC', string): 
     decoded = unidecode.unidecode(char) 
     if latin.match(decoded): 
      yield char 
     else: 
      yield decoded 

def clean_string(string): 
    return "".join(char_filter(string)) 

print(clean_string(u"vis-à-vis “Beyoncé”’s naïve papier–mâché résumé")) 
# prints vis-à-vis "Beyoncé"'s naïve papier-mâché résumé 
+0

Esta solución es, en última instancia, un gran diccionario de cartografía. Y algunas de las decisiones de mapeo allí son inusuales. Por ejemplo, asignará el guión em (-) a dos guiones (-). –

0

No existe tal solución "correcta", porque para cualquier carácter Unicode dado que no hay "contraparte ASCII" definido.

Por ejemplo, tome los caracteres aparentemente simples que desee asignar a comillas simples y dobles ASCII y guiones. Primero, generemos todos los caracteres Unicode con sus nombres oficiales. En segundo lugar, permite encontrar todas las comillas, guiones y guiones de acuerdo con los nombres:

#!/usr/bin/env python3 

import unicodedata 

def unicode_character_name(char): 
    try: 
     return unicodedata.name(char) 
    except ValueError: 
     return None 

# Generate all Unicode characters with their names 
all_unicode_characters = [] 
for n in range(0, 0x10ffff): # Unicode planes 0-16 
    char = chr(n)    # Python 3 
    #char = unichr(n)   # Python 2 
    name = unicode_character_name(char) 
    if name: 
     all_unicode_characters.append((char, name)) 

# Find all Unicode quotation marks 
print (' '.join([char for char, name in all_unicode_characters if 'QUOTATION MARK' in name])) 
# " « » ‘ ’ ‚ ‛ “ ” „ ‟ ‹ › ❛ ❜ ❝ ❞ ❟ ❠ ❮ ❯ ⹂ 〝 〞 〟 " 

# Find all Unicode hyphens 
print (' '.join([char for char, name in all_unicode_characters if 'HYPHEN' in name])) 
# - ­ ֊ ᐀ ᠆ ‐ ‑ ‧ ⁃ ⸗ ⸚ ⹀ ゠ ﹣ - 

# Find all Unicode dashes 
print (' '.join([char for char, name in all_unicode_characters if 'DASH' in name and 'DASHED' not in name])) 
# ‒ – — ⁓ ⊝ ⑈ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ╌ ╍ ╎ ╏ ⤌ ⤍ ⤎ ⤏ ⤐ ⥪ ⥫ ⥬ ⥭ ⩜ ⩝ ⫘ ⫦ ⬷ ⸺ ⸻ ⹃ 〜 〰 ︱ ︲ ﹘ 

Como se puede ver, tan fácil como este ejemplo es, hay muchos problemas. Hay muchas comillas en Unicode que no se parecen en nada a las comillas en US-ASCII y hay muchos guiones en Unicode que no se parecen en nada al signo de guión negativo en US-ASCII.

Y hay muchas preguntas. Por ejemplo:

  • ¿se debe reemplazar el símbolo "SWUNG DASH" (SW) por un guión ASCII (-) o una tilde (~)?
  • ¿Debería reemplazarse "CANADIAN SYLLABICS HYPHEN" (CAN) por un guión ASCII (-) o un signo igual (=)?
  • caso de que el "apunta hacia la izquierda COMILLA ANGULAR SIMPLE" (<) se sustituye con una comilla ASCII ("), un apóstrofo (') o un signo menor que (<)?

Para establezca una contraparte ASCII "correcta", alguien debe responder estas preguntas en función del contexto de uso. Por eso, todas las soluciones a su problema se basan en un diccionario de mapas de una manera u otra. Y todas estas soluciones proporcionarán resultados diferentes.

Cuestiones relacionadas