Tokenización de texto no inglés en Python

Tengo un archivo de texto persa que tiene algunas líneas como esta:

ذوب 6 خوی 7 بزاق ،آب‌دهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف 

Quiero generar una lista de palabras de esta línea. Para mí, los bordes de las palabras son números, como 6, 7, etc. en la línea anterior y también el carácter. por lo que la lista debe ser:

 [ 'ذوب','خوی','بزاق','آب‌دهان','یم','زهاب','آبرو','حیثیت' ,'شرف'] 

Quiero hacer esto en Python 3.3. Cuál es la mejor manera de hacer esto, realmente aprecio cualquier ayuda en esto.

EDITAR:

Obtuve varias respuestas, pero cuando las usé para otro caso de prueba no funcionaron. El caso de prueba es este:

 منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن 

y espero tener una lista de tokens como esto:

 ['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن'] 

Usando el paquete regex :

 >>> import regex >>> text = 'ذوب 6 خوی 7 بزاق ،آب‌دهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' >>> regex.findall(r'\p{L}+', text.replace('\u200c', '')) ['ذوب', 'خوی', 'بزاق', 'آبدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف'] 
  • El texto contiene ZERO WIDTH NON-JOINER (U + 200C). eliminado el personaje usando str.replace .
  • \p{L} o \p{Letter} coincide con cualquier tipo de letra de cualquier idioma.

Ver el tutorial de Regex – Caracteres y propiedades de Unicode .

ACTUALIZAR

Para incluir también U + 200C, use [\p{Cf}\p{L}]+ lugar ( \p{Cf} o \p{Format} coincide con el carácter de formato invisible):

 >>> regex.findall(r'[\p{Cf}\p{L}]+', text) ['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف'] 

Se ve diferente de lo que quieres, pero son iguales:

 >>> got = regex.findall(r'[\p{Cf}\p{L}]+', text) >>> want = [ 'ذوب','خوی','بزاق','آب‌دهان','یم','زهاب','آبرو','حیثیت' ,'شرف'] >>> print(want) ['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف'] >>> got == want >>> got[:3] ['ذوب', 'خوی', 'بزاق'] >>> got[4:] ['یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف'] 

Actualización2

Algunas palabras en la pregunta editada contienen un espacio.

 >>> ' ' in 'منهدم کردن' True 

Agregué \s en el siguiente código para que coincida también con los espacios, luego elimine los espacios iniciales y finales de las cadenas coincidentes, luego filtre las cadenas vacías.

 >>> text = 'منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن' >>> want = ['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن'] >>> [x for x in map(str.strip, regex.findall(r'[\p{Cf}\p{L}\s]+', text)) if x] == want True 

Use re.split para dividir en espacios en blanco ( \s ), dígitos ( \d ) y el carácter ، .

 # python 3 import re INPUT = 'ذوب 6 خوی 7 بزاق ،آب‌دهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' EXPECTED = [ 'ذوب','خوی','بزاق','آب‌دهان','یم','زهاب','آبرو','حیثیت' ,'شرف'] OUTPUT = re.split('[\s\d،]+', INPUT) assert OUTPUT == EXPECTED print('\n'.join(OUTPUT)) 

Tenga en cuenta que el \u200c que está viendo en la matriz de salida es un carácter que no se puede imprimir y en realidad está contenido en la cadena original. Python se está escapando porque muestra la representación de la matriz y las cadenas contenidas, no imprime la cadena para mostrarla. Aquí está la diferencia:

 INPUT = 'ذوب 6 خوی 7 بزاق ،آب‌دهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' print(INPUT) ذوب 6 خوی 7 بزاق ،آب‌دهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف print(repr(INPUT)) # notice the \u200c below 'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' print(['in', 'an', 'array', INPUT]) # the \u200c is also shown when printing an array ['in', 'an', 'array', 'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف'] 

Esto es similar a cómo Python maneja los caracteres de newline :

 >>> 'new\nline' 'new\nline' >>> print 'new\nline' new line 

Editar:

Aquí está la expresión regular para su muestra actualizada que usa la estrategia findall de falsetru, pero usa el módulo de re incorporado:

 OUTPUT = [s.strip() for s in re.findall(r'(?:[^\W\d_]|[\s])+', INPUT) if s.strip()] 

El patrón (?:[^\W\d_]|[\s])+ es un poco extraño, ya que el módulo re de Python no tiene equivalente a las “Letras” \p{L} regex, así que en su lugar usamos la solución propuesta aquí https://stackoverflow.com/a/8923988/66349

 [^\W\d_] - (not ((not alphanumeric) or digits or underscore)) 

Entonces, en resumen, haga coincidir uno o más caracteres ( + ) que sean ( | ): letras Unicode [^\W\d_ , o espacios en blanco \s .

El método de falsetru es probablemente más legible, pero requiere la biblioteca de terceros.