6. Documentos digitales como cadenas

Ya que has probado Python, vamos a meter mano al plato principal, la computación textual. El único inconveniente es que no tienes un texto todavía, así que toca encontrar uno. Pero antes hay que tener un lugar donde guardarlo,

6.1. Como manejar el directorio de trabajo

6.1.1. Como configurar el directorio de trabajo global de Spyder

En la carpeta de documentos de tu computadora, crea una carpeta nueva que se llama pyScripts.

Abre Spyder y abre el menu de Preferences. Selecciona Global working directory y haz los cambios siguientes:

  • At start-up, the global working directory is … the following directory (navega a “pyScripts” y pínchala).
  • Files are opened from: … the global working directory.
  • Files are created in: … the global working directory.

Cierra Spyder y vuelve a abrirlo.

6.1.2. Como inspeccionar el directorio de trabajo actual con os

Python va a bajar un documento de Internet a tu carpeta de pyScripts, pero quiero confirmar que la puede encontrar. La organización de las carpetas le corresponde al sistema operativa, y Python tiene un módulo incorporado que se llama os que comunica con él. Impórtalo y efectúa la instrucción de 2:

>>> import os
>>> os.getcwd()
'/Users/harryhow/Documents/pyScripts'
>>> os.listdir('.')
[]

En 2, el cwd de os.getcwd() abrevia “current working directory”, el directorio de trabajo actual. Es la carpeta en la que Python abre y guarda ficheros. Vas a procurar que sea sólo pyScripts. Línea 4 alista el contenido de pyScripts. . abrevia la expresión regular .+. Como no le has metido nada, está vacía y la instrucción devuelva la lista vacía. [1]

6.1.3. Otros métodos de directorios de os

Si no has podido hacer nada de lo anterior, lo puedes hacer a mano con Python, de esta forma:

>>> import os
>>> os.getcwd()
>>> os.chdir('/Users/{your_user_name}/Documents/')
>>> os.makedirs('pyScripts')
>>> os.listdir('.')
[]
>>> os.path.exists('/Users/{your_user_name}/Documents/pyScripts')
True

Si no has importado os, lo haces primero y luego averiguas cuál es directorio de trabajo actual en 2. Se supone que no es pyScripts y lo tienes que crear. En 3 se cambia el directorio de trabajo actual al de documentos y en 4 se crea pyScripts allí. Las próximas dos instrucciones comprueban que se haya hecho bien. Línea 5 alista el contenido de pyScripts, que no debería tener nada. Línea 7 recorre el sendero de pyScripts para ver si está de verdad allí.

Ahora toca por fin meter un documento allí.

6.2. Como bajar un texto de un archivo en línea y guardarlo en tu disco duro

Hay varios archivos de Internet que disponen de textos con que podrías empezar, pero el que más me gusta es el del Proyecto Gutenberg.

6.2.1. Proyecto Gutenberg

Dirige tu navegador de web a la página principal de Project Gutenberg. Como ves, ofrece más de 42,000 e-libros gratis. Pincha el enlace de Browse catalog, y en el centro de la página nueva hay una lista de idiomas que disponen de e-libros. En el renglón de “Languages with more than 50 books” está el enlace del español. Pínchalo y desplaza la página abajo hasta encontrar “Cervantes Saavedra, Miguel de, 1547-1616”. Pincha “Novelas y teatro”. La secuencia de enlaces se puede resumir como:

Project Gutenberg ‣ Browse catalog ‣ Spanish ‣ Cervantes Saavedra, Miguel de, 1547-1616 ‣ Novelas y teatro

Deberías estar mirando esta página:

_images/6-ProjGutNovelasTeatro.png

Ahora vas a aprender a bajar el fichero llamado “Plain Text UTF-8” con Python.

6.2.2. Como descargar un fichero con requests

El módulo que más se recomienda para bajar ficheros de Internet se llama requests. No es un módulo incorporado en Python pero se incluye en la distribución de Anaconda, así que lo puedes importar sin problema. Requests necesita saber dónde está el fichero, o sea, necesita saber su dirección de Internet. En la jerga de Internet, una dirección es un “uniform resource locator” o “URL”, lo que se expresa en español como localizador uniforme de recursos o ‘LUR’. El método get de requests se encarga de la descarga:

>>> import requests
>>> lur = 'http://www.gutenberg.org/cache/epub/15115/pg15115.txt'
>>> descarga = requests.get(lur).text

Ahora querrás saber algo de lo que has descargado:

>>> type(descarga)
<type 'unicode'>
>>> len(descarga)
363600
>>> descarga[:150]
u'The Project Gutenberg EBook of Novelas y teatro, by Cervantes\r\n\r\nThis eBook is for the use of anyone anywhere at no cost and with\r\nalmost no restricti'

Date cuenta que requests descarga el documento en Unicode, lo cual te facilita bastante el trabajo.

6.2.3. Como guardar un fichero en tu disco duro con open(), write() y close()

Sacar un fichero de Python y guardarlo en tu disco duro conlleva tres pasos que no son del todo intuitivos. Conviene que los conozcas cuanto antes. Lo complejo del proceso es que hay que crear un fichero vacío o ficticio (“dummy”) que contiene el documento temporalmente antes de guardarlo a disco. Los pasos son:

>>> fitemp = open('NovelasTeatro.txt','w')
>>> fitemp.write(descarga.encode('utf8'))
>>> fitemp.close()

En 1 se crea un fichero ficticio temporal con open() en su modo de 'w' (“write”) y se le da un nombre. Si miras la carpeta de pyScripts, verás que ‘NovelasTeatro.txt’ ha aparecido allí. En 2 se escribe la cadena descargada al fichero ficticio temporal. Como está en Unicode, se codifica en UTF-8. En 3 se cierra el fichero ficticio temporal para liberar los recursos que se le había dedicado.

Al fichero ficticio temporal no se le puede inspeccionar, ni cuando está abierto ni cuando está cerrado. Si lo intentas, Python retorna un error:

>>> fitemp
<open file FileSystemPathPointer('/Users/{your_user_name}/nltk_data/pytextos/NovelasTeatro.txt'), mode 'w' at 0x104d58270>
<closed file 'NovelasTeatro.txt', mode 'w' at 0x102109270>

Ahora que tienes un texto, échale un vistazo.

6.3. Como manejar un fichero en tu disco duro

6.3.1. Como leer un fichero con open(), read() y close()

Manejar un fichero que ya está guardado en tu disco duro conlleva el mismo paso intermediario de crear un fichero ficticio temporal con open():

>>> fitemp = open('NovelasTeatro.txt','r')
>>> texto = fitemp.read()
>>> fitemp.close()

Como antes, en 1 open() necesita un fichero y un indicio del modo con el que abrirlo. Suponiendo que el directorio de trabajo actual es pyScripts, el sendero al fichero se reduce a su nombre, y el modo es 'r' de “read”. En 2 se vierte el contenido de fichero al variable texto. Al acabar, en 3 se cierra el fichero ficticio temporal para liberar los recursos que se le había dedicado.

Puesto que la salida de open() es la entrade de read(), los dos métodos se pueden combinar haciendo open() un atributo de read() y prescindiendo del fichero ficticio temporal:

>>> texto = open('NovelasTeatro.txt', 'r').read()

Ahora puedes inspeccionar texto, una cadena de 370503 caracteres, el cual va a ser el punto de partida para la computación textual:

>>> type(texto)
>>> len(texto)
370503

Recuerda que el texto está todavía en UTF-8.

6.3.2. the modes of open() ‘rU’

6.3.3. Como dividir un documento en sub-textos

Sé que Cervantes’ Novelas y Teatro consiste en siete obras. ¿Cómo lo sé? Miré el índice. Empieza con la palabra INDICE y termina con el número de página 275. ¿Se te ocurre una forma de extraer este texto del documento para que lo veas tú también?

Podrías valerte de un corte, pero tienes que saber el índice de INDICE y 275 (los números de página sólo están en el índice y no en cada página del documento). ¿Recuerdas find()?:

>>> prin = texto.find('INDICE')
prin # 370503
>>> fin = texto.find('275')
fin # 351279

¿Puedes utilizar estos dos índices para efectuar el corte texto[prin:fin]?

Sí, pero no va a resultar tan bonito como yo quisiera. el problema es que texto.find('275') sólo encuentra el índice del primer carácter de la cadena, 2. Tienes que sumarle 2 para que llegue al 5. Bueno, la verdad es que son 3, porque el corte va hasta, sin incluir, el último carácter. print muestra el resultado:

>>> print texto[prin:fin+3]

INDICE
                                                       PÁGS.

    LA GITANILLA                                          5

    LA ILUSTRE FREGONA                                   65

    HISTORIA DE LOS TRABAJOS DE PERSILES Y SIGISMUNDA   119

    NOVELA Y COLOQUIO QUE PASÓ ENTRE CIPIÓN Y BERGANZA  181

    EL RETABLO DE LAS MARAVILLAS                        213

    EL CERCO DE NUMANCIA                                231

    PEDRO DE URDEMALAS                                  275

Armado con este conocimiento, quiero que extraigas una sola obra para analizarla, la primera, La gitanilla. Si el texto de esta novela comienza con el primer caso de “LA GITANILLA” – el del título – y termina justo antes del título siguiente, “LA ILUSTRE FREGONA”, ¿cómo lo extraerías? Y, a propósito, una vez que lo hayas extraído, guárdalo en un fichero de pyScripts con el nombre de Gitanilla.txt. Intenta hacerlo por tu cuenta y luego mira Solucines a “Archivos en y fuera de línea” comprobar tu solución.

6.4. The Natural Language Toolkit, NLTK

By far the most convenient place to look would be the corpora that were collected for the Natural Language Toolkit, which we will hereafter refer to as NLTK. (We will refer to these corpora here and there in this book, but they have the disadvantage of being almost entirely in English. Since we want to go beyond English, we will begin our search elsewhere. And we should add parenthetically that the NLTK corpora have a second disadvantage: they are ‘pre-digested’ to make working with them easier than with a ‘raw’ text gathered in the wild. It is our experience that the short-term gain from this pre-processing comes at long-term expense: you will not have enough experience with real texts to be able to deal with them efficiently. So we eschew the easy path for the hard one. You will be a better person for it.)

6.4.1. How to get NLTK

The first step is to check whether you already have the nltk module installed in your Python distribution by typing import nltk in the Python interpreter of Spyder’s console. If Python returns the prompt to you, then nltk is installed and you can go on and download its corpora. If you get an error message like this one …

>>> import nltk
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ImportError: No module named nltk
>>>
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ImportError: No module named nltk

you must install nltk.

6.4.2. How to download the NLTK corpora

The instructions for Installing NLTK Data from the NLTK website are as follows:

>>> import nltk
>>> nltk.download()
showing info http://nltk.github.com/nltk_data/

This should open a window like this one (on the Mac, it is with the rocketship icon):

_images/6-nltkdata.png

Look at the bottom line labelled Download Directory. On my Mac, the path is /Users/harryhow/nltk_data. Keep this in mind for a while. [2]

Click on Book and then the Download button. The download could take a while, so be patient. The bar in the bottom right corner records its progress. Once it is complete, double-check that it worked by giving the following commands in Python:

>>> from nltk.corpus import brown
>>> brown.words()
['The', 'Fulton', 'County', 'Grand', 'Jury', 'said', ...]

We note in passing that NLTK provides an easier way of getting the path to a file with the nltk.data.find() method, which takes as its only argument the path to the file within the nltk_data folder. This is the kind of simplification that motivates us to recommend keeping your data in the nltk_data folder:

>>> sendero = nltk.data.find('pytextos/Gitanilla.txt')

6.5. Summary

6.6. Additional practice

Crea documentos separadas para todas las obras de NovelasTeatro.txt.

¿Cuál es la obra más reciente en español que puedes encontrar en el Proyecto Gutenberg?

6.7. Further reading

6.8. Appendix

Footnotes

[1]The Mac may include a file called ‘.DS_Store’ in the list. Don’t worry about it.
[2]At some point I may advise that the NLTK corpora should go in the Documents directory, requiring a change of the path to /Users/harryhow/Documents/nltk_data

Last edited: February 10, 2015