Interescuelas 2011

XIII Jornadas Interescuelas/Departamentos de Historia
Catamarca, Argentina, 10-13 de agosto de 2011

Mesa temática 46: Relaciones entre asociaciones intermedias y política, 1940-1960

Coordinadores:
Acha, Omar (UBA-CONICET) omaracha@gmail.com
Quiroga, Nicolás (UNMdP-CONICET) nfquirog@gmail.com

La mesa se propone como un ámbito para debatir sobre dos décadas de política y asociacionismo (1940-1960). El recorte temporal tiene como centro el primer peronismo pero pretende abarcar el momento anterior y el posterior para incorporar otros desarrollos de un orden asociativo que en diversos planos (cooperativismo, fomentismo, clubes barriales, sindicatos, organismos políticos de base, instituciones culturales, religiosas, etc.) hizo más complejas las dinámicas políticas del período en su conjunto –y que sin embargo ha sido poco o nada explorado–.
Convocamos a la presentación de trabajos que aspiren a ampliar la indagación sobre formas específicas de acción política en organizaciones intermedias, de modos de activación política de nivel celular, de interpelaciones identitarias en los intersticios de una sociedad que tradicional y principalmente la historiografía consideró en sus vínculos con el estado y las dirigencias políticas. Esperamos conocer y discutir aproximaciones que se ocupen de la relación de asociaciones con los partidos políticos (peronismo, socialismo, comunismo, etc.), con las corporaciones, con los gobiernos, las instituciones educativas, los consumidores, etc. durante el período que proponemos.

Información general para la presentación de resúmenes

El resumen debe “cargarse” electrónicamente, hasta el 15 de noviembre de este año, en:

http://blogs.ffyh.unc.edu.ar/jornadasinterescuelas/

Los autores, si lo desean, pueden enviar, además, una copia del resumen a uno de los coordinadores (omaracha@gmail.com ; nfquirog@gmail.com ).
En caso de que haya inconvenientes con la carga electrónica no duden en comunicarse con los coordinadores.
Los resúmenes tendrán un mínimo de 1500 y un máximo de 1800 caracteres. Fuente Times New Roman, tamaño 12, interlineado sencillo. Dada la magnitud de estas Jornadas se admitirá una presentación por persona en forma individual o en co-autoría (máximo dos coautores).
La fecha última para la presentación de las ponencias está prevista para el 11 de abril de 2011.

Tecnologías del orgasmo y otros artilugios de la modernidad

Post cruzado desde Clionauta


Vibrator pub



Hace justamente ahora una década apareció un volumen titulado The Technology of Orgasm: “Hysteria,” Vibrators and Women’s Sexual Satisfaction (Johns Hopkins University Press). El libro lo escribió Rachel P. Maines, que ahora es profesora en la Cornell University School of Electrical and Computer Engineering y cuyo campo de estudio es la historia de la tecnología. La obra tuvo un enorme impacto, incluso antes de aparecer, y recibió abundantes críticas, algunas no muy favorecedoras y otras casi entusiastas, como la del History Workshop Jurnal. En castellano, se publicó parcialmente en México en Debate Feminista en 2001. En Italia apareció ese mismo año de 2001 (Marsilio) y en Francia se acaba de editar, poco antes del verano (Payot), también con división de opiniones.
Pues bien, la Johns Hopkins University Press acaba de presentar a finales de septiembre un nuevo libro de la profesora Maines, aunque es de presumir que mucho menos polémico. Su título es Hedonizing Technologies: Pathways to Pleasure in Hobbies and Leisure y según la editora

Hedonizing Technologies
quotep

"Rachel P. Maines’ latest work examines the rise of hobbies and leisure activities in Western culture from antiquity to the present day. As technologies are “hedonized,” consumers find increasing pleasure in the hobbies’ associated tools, methods, and instructional literature. Work once essential to survival and comfort —gardening, hunting, cooking, needlework, home mechanics, and brewing— have gradually evolved into hobbies and recreational activities. As a result, the technologies associated with these pursuits have become less efficient but more appealing to the new class of leisure artisans. Maines interprets the growth and economic significance of hobbies in terms of broad consumer demand for the technologies associated with them."

Jacques Rancière y la emancipación: Crítica de la crítica del ‘espectáculo’

Post cruzado desde Clionauta

Este blog [Clionauta] lleva ya lo suyo y acumula un buen número de entradas. De entre todas ellas, una de la más leídas (y la más citada) es la que hace referencia a Jacques Rancière. Así que, como homenaje a los muchos lectores que le siguen, añado otra entrada relacionada con este pensador.
Tomamos para la ocasión la entrevista que la Revue internationale des livres et des idées publicó este verano, realizada en el Musée des Beaux-Arts de Saint-Étienne en diciembre de 2008. En ella, el enrevesado pensador francés retoma los principales argumentos desarrollados en Le Spectateur émancipé (La fabrique, 2008), y más particularmente su crítica de la crítica del espectáculo (tal como es teorizada por Guy Debord) y su impacto sobre las posibilidades de emancipación intelectual, política y estética.
Recordemos, por otra parte, algunas novedades relativas a este autor. Por un lado, sus recientess libros Et tant pis pour les gens fatigués. Entretiens (Editions Amsterdam, 2009) y Moments politiques. Interventions 1977-2009 (La Fabrique, 2009). Por otro, Jacques Rancière. Politique de l'esthétique (Archives contemporaines, 2009), un volumen preparado por Jérôme Game y Aliocha Wald Lasowski que recupera un seminario celebrado en Lyon en abril de 2008.
Jérôme Game (JG): En Le Spectateur émancipé, su perspectiva es la de una crítica de la crítica del espectáculo: con este fin, reconstruye la red de presupuestos teóricos. ¿Puede precisar en qué consiste esta red y cómo funciona?
Jacques Rancière (JR): Básicamente, funciona de manera simple, en la medida en que, inicialmente, tenemos la condena del teatro como lugar del espectador, que se remonta al menos a Platón y consiste básicamente en dos proposiciones fundamentales. En primer lugar, ser un espectador es una mala cosa, porque un espectador es alguien que mira y en consecuencia se sitúa frente a las apariencias -y por tanto le falta la verdad, que está obviamente tras la apariencia o por debajo de lo que se ve. Así pues, una primera tesis fundamental: ser espectador es mirar y mirar es mala cosa, porque eso no es conocer. El segundo argumento, relacionado con el anterior, aunque puede estar disociado, consiste en decir: "ser un espectador es malo, porque un espectador está sentado, sin moverse". Por tanto, ser un espectador es estar pasivo y, por supuesto, lo bueno es la actividad. La cuestión del espectador ha estado enmarcada inicialmente y durante mucho tiempo por dos pares de oposiciones fundamentales, a saber: mirar y conocer, por un lado, y ser activo o pasivo, por otro. Creo que en el fondo lo importante es la movilidad de este dispositivo teórico: funciona primero en el marco platónico donde trata de poner en orden la ciudad -"cada uno en su lugar"- y, por tanto, de prohibir el teatro, ya que sólo pasa a ser el lugar del desdoblamiento, el lugar que nos hace que no sepamos quién es quién o quién hace qué ni, por tanto, cuándo queda amenazado el orden de la ciudad. Pero, al mismo tiempo, esta oposición es susceptible de ser reproducida y desplazada constantemente, con lo que puede cargar con todos los valores del progreso, la revolución y la emancipación. Lo vemos muy claramente ya en el siglo XVIII con Rousseau, que retoma esta crítica del espectáculo -pero centrándose, más que en la oposición entre mirar y conocer, en la de mirar y actuar, concluyendo que si uno busca algo en el teatro es precisamente porque uno ha renunciado a ello en la vida real. En consecuencia, lo que opone a la escena teatral es la fiesta popular de Ginebra o la fiesta cívica en la antigua Esparta. Así, queda atrapado en la oposición platónica, pues ya Platón oponía el desdoblamiento del teatro al coro o a la ciudad que incorporan, y que no se ponen frente a sí mismos, que no contemplan el espectáculo sino que estan actuando. Lo que Rousseau retoma es algo parecido, más aún cuando algo no deja de ser retomado: esta crítica de la mimesis se convierte en el siglo XIX en el núcleo de la crítica social. Podemos pensar en la forma con la que Feuerbach y Marx la retoman, con la idea de que el fundamento de la dominación es la separación entre el hombre y su esencia, que se proyecta hacia fuera, allí, en la distancia, frente a él. A partir de ahí, el platonismo se convierte en revolucionario denunciando a todas esas gentes que son espectadores, es decir, a aquellos que ante todo se encuentran en la ignorancia -dominados al estar en un lugar donde abren los ojos como cretinos y, desde luego, no ven cómo trabaja la máquina- y, en segundo lugar, lo que es más radical, eso que Marx toma de Feuerbach y que Guy Debord actualizará en nuestro tiempo con todos los ornamentos que sabemos: esa idea de que ser un espectador es extrañarse frente a lass propias vida y actividad. ¿Qué sucede entonces? Ocurre que la crítica platónica de la mimesis deviene la explicación de las razones de la miseria social -obviamente con la contrapartida de que toda crítica social va a querer liberar a los espectadores de su ignorancia, y acto seguido de su pasividad. Y para liberar a los ignorantes, antes hay que constituirlos como tales.
J. G. : Después de Artaud y Brecht, usted menciona en particular el caso de Debord en torno a una paradoja: por un lado, él sitúa la verdad como una no-separación, pero, por otro lado, se plantea como algo malo la contemplación de las apariencias separadas de su verdad. En otras palabras, cuanto más antiplatónico parece menos lo es. ¿Puede detallar cómo funciona esta contradicción?
J. R. : Hay una famosa frase de Guy Debord, que parece antiplatónica, que dice; "el hombre, cuanto más contempla menos es", dada la oposición entre ser y ver. Pero, finalmente, es lo mismo, pues lo que le falta al espectador es precisamente la conciencia de que lo que tiene delante de él es su propia realidad, su propia esencia, su propia vida, su propia acción, que están separadas, que se convierten en extrañas. En ese momento, la crítica de la mimesis se convierte esencialmente -ese es el título de una película de Debord- en una crítica de la separación, es decir, la forma de situar el espectáculo como el mal absoluto, identificando el proceso por el cual el hombre proyecta su esencia fuera de sí mismo. De esto se sigue una distancia y una impotencia radicales: como todo el mundo está en el espectáculo, no hay ninguna razón para que nadie se salga jamás, ni siquiera quien conoce la razón de ese espectáculo. Hay una frase de Guy Debord que dice: "en el mundo realmente invertido, la verdad es un momento de falsedad": más o menos significa que saber el motivo del espectáculo no cambia el control del espectáculo. Queda, pues, finalmente, la autoridad de la voz que enuncia el poder del espectáculo. Esto es particularmente evidente al ver las películas de Debord ya que en ellas hay un desfile de imágenes indiferente en cierto sentido (no es absolutamente cierto; volveré sobre ello) y sólo cuenta la voz que dice: "estás ante estas imágenes, mirando como un cretino, pues estas imágenes son como tu propia muerte". Esa voz que señala la separación, en cierto sentido la consagra: dice que todos estamos en las imágenes -así será siempre-, pero nunca nos saca en ellas. Por otra parte, la película confía a las imágenes el encargo de decirnos que hay una solución, a saber: no hay que mirar, tenemos que actuar. Es muy interesante ver en las películas de Debord, especialmente en La Société du spectacle, los préstamos que toma de los westerns. Uno podría pensar que es una parodia cuando vemos a Errol Flynn cargando a su manera, espada en ristre; se podría pensar que se mofa de esos cretinos imperialistas americanos y de su mitología heroica, pero eso no es totalmente cierto. En cambio, nos lo propone como ejemplo, pues él dice que eso es lo que se debe hacer: hay que hacer como Errol Flynn o como John Wayne, corriendo al asalto de sudistas o indios. Éste es el modelo para lo que hay que hacer: el ataque de los guerreros proletarios contra la dominación del espectáculo. Al mismo tiempo, por supuesto, queda un espectáculo que confirma la autoridad de la voz que dice: "Siempre estará dentro". Podemos entender de esta manera cómo el situacionismo se ha convertido en la actual versión banalizada, como crítica del consumidor democrático embrutecido por los medios de comunicacion. Lo que hay detrás es la forma en la que la tradición crítico-marxista revolucionaria ha absorbido una serie de supuestos no igualitarios: están los activos y los pasivos, los que miran y los que saben. Básicamente, esto equivale a decir: hay quienes son capaces y hay quienes no lo son. A partir de ahí, hay varias estrategias posibles: o bien creemos que necesitamos una vanguardia que una a la gente y sea capaz de inculcar en la cabeza de los incapaces la forma de escapar, o bien adoptamos la posición del gran señor desencantado que concluye que, efectivamente, el momento de actuar ha pasado y que sus contemporáneos están condenados para siempre a quedarse dentro del espectáculo.
J. G. : Usted enlaza esta cuestión con la de la emancipación intelectual tal como la analiza en El maestro ignorante en torno a la figura de Jacotot. Usted establece una diferencia entre denuncia de la alienación (Brecht, Debord) y reapropiación de la relación con uno mismo que permite la lógica de la emancipación, lo que usted llama la subjetivación. El problema es que, en efecto, al denunciar la pasividad se supone una diferencia esencial: la diferencia activo/pasivo, con el reparto de posiciones y capacidades asociadas. Por el contrario, a su modo de ver, la emancipación sitúa el acto de ver como la acción que transforma o confirma esa asignación a un lugar específico. ¿Puede volver a lo que redistribuye lo sensible a través de esa reapropiación individual, y sobre la cuestión del poder del principio de igualdad como un nuevo modo común?
J. R. : ¿Cuál es el nucleo de la crítica de Jacotot y qué supone de positivo? ¿La idea de la emancipación intelectual, que opone a la instrucción del pueblo? Lo que es esencial en Jacotot es la idea de que, en realidad, todo depende del punto de partida. O se parte de la la desigualdad o de la igualdad. El pedagogo común, no sólo en el sentido de profesor sino también de pedagogo político, de líder como educador del pueblo o militante que le hace tomar conciencia, siempre parte de la desigualdad. La lógica habitual de la pedagogía es decir: "Se comienza con niños pequeños que no saben nada, gente común que está llena de prejuicios y no puede ver lo que tiene ante sus ojos y luego, poco a poco, progresivamente, con orden, los lleva desde su posición de desigualdad hacia una de igualdad". Pero, por supuesto, ya que el maestro es siempre el que organiza el viaje de la desigualdad a la igualdad, la desigualdad se repite indefinidamente en el propio mecanismo que pretende suprimir. La reducción de las desigualdades deviene la verificación interminable de la misma desigualdad. Lo interesante es la forma en la que, como hemos visto, ese mismo proceso ocurre en el teatro. Lo curioso es que los reformadores del teatro, en particular desde principios del siglo XX, quisieron incorporar la crítica del teatro dentro del teatro. Platón o Rousseau decían: "El teatro es malo, hace que las personas sean ignorantes y pasivas" y, finalmente, se propone que sea el propio teatro el que repare su falta, con lo que el pedagogo haría que las personas fueran activas. Sabemos la importancia que tuvo en el siglo XX la idea de que el teatro debe hacer que los espectadores salgan de su pasividad. Puede ser a la manera de Artaud: que no haya espectadores frente a la escena, sino que estén rodeados por la acción, como inmersos en el círculo de la acción, devueltos a sus energías vitales, que se han perdido en el espectáculo. Puede ser la idea de Piscator, la de que el teatro debe ser algo así como una asamblea popular. Pueden ser todas estas prácticas tan extendidas en la Unión Soviética en los años posteriores a la Revolución, en tiempos de Meyerhold, que trataban de transformar la escena treatral en una acción comunitaria. Siempre ha existido la idea de que el teatro es en sí mismo una comunidad, que esa comunidad se ha perdido, que es necesario reencontrarla y que hay que reencontrarla precisamente aboliendo la separación entre visión y acción. El problema, como sabemos, es que, a pesar de todo, a la lógica del teatro le ocurre lo mismo que a la lógica pedagógica, es decir, que para que el espectador sea activo los directores tienen que hacer un gran despliegue de medios, con edificios espectaculares, proyecciones cinematográficas, intervenciones de la supuesta vida exterior sobre el escenario, y así sucesivamente, y todas estas formas de hacer que el espectador sea activo son, de hecho, formas de aumentar el poder de la maquinaria teatral y de reforzar más aún la posición de espectador, que queda paralizado por lo que le llega.
Yo no soy un historiador del arte ni un filósofo del arte, etc. Trabajo sobre la experiencia estética como experiencia que produce una desviación con respecto a las formas de la experiencia ordinaria. En el fondo, ¿que hay en el corazón del régimen estético del arte? Constituir precisamente una especie de esfera de experiencia que rompa con las lógicas de dominación -se está refiriendo al libre juego, ese concepto tomado de Kant y de Schiller y que define con precisión la salida de un relación jerárquica de dependencia, el juego del espectador libre ante la forma que está frente a él. Bourdieu y los sociólogos se burlan diciendo: "Hay que ver lo cretinos e ingenuos que son esos filósofos, que no saben que en realidad los trabajadores y los burgueses tienen sus propios gustos, sus maneras de ver, sus formas de juzgar y así sucesivamente". Pero, precisamente, lo que está en el corazón de la ruptura que representa la experiencia estética es que las cosas se toman a la inversa. En lugar de decir eso de que "ya se sabe que en realidad todas las personas tienen los sentidos que les convienen, y así sucesivamente", lo que se propone es una experiencia que es una experiencia de perturbación de los sentidos, no en el sentido de Rimbaud (aunque cabe aquí) sino más bien como una forma de experiencia que rompe con respecto a las formas normales de la experiencia que son las formas de dominación. Si lo comento es porque lo he vivido, reconocido en toda la historia de la emancipación de los trabajadores. ¿Cómo se supone que empieza la emancipación obrera? Nada de explotación, dominación del capital y todo eso. Todo el mundo sabe de eso y los explotados siempre lo han sabido. La emancipación de los trabajadores es la posibilidad de constituir formas de decir, maneras de ver, maneras de ser que rompan con las impuestas por el orden de dominación. Así que la pregunta no es saber quién es el explotado; en cierto sentido, la pregunta se puede incluso ignorar. Y en el centro de la emancipación obrera hay ese tipo de decisión, la de ignorar en cierto modo que estamos obligados a trabajar con nuestros brazos mientras otros disfrutan de los beneficios de la mirada estética. Eso es lo que he comentado en Le Spectateur émancipé a popósito de ese breve texto de un modesto carpintero, que ya había trabajado también Gabriel Gauny, en el que relata su jornada de trabajo. Trabaja en una residencia burguesa, pone el parquet, es explotado por el patrón, trabajaba para el propietario, la casa no es suya, pero describe la forma en la que se apropia del espacio, del lugar, de la perspectiva que abre la ventana. En última instancia, ¿qué significa eso? Que realiza una especie de disociación entre sus brazos y su visión, para fijar una mirada que es la propia de un esteta. Por supuesto, Bourdieu diría: "Ahí tienes la mistificación". Pero yo diría que hemos de tomar las cosas a la inversa: lo que importa es, precisamente, la no adaptación, la no identificación frente a un modo de identidad, frente a un modo de ser, de sentir, de percibir, de hablar, el que va adherido a la experiencia sensible ordinaria tal como está organizada por la dominación. Todo esto ha sido muy importante para mi. Es lo que quiere decir emancipación, lo que significa esa especie de ruptura, esa oposición a una forma de organización sensible quebrada en el sentido más material, es decir, que finalmente los brazos hacen su trabajo y luego los ojos van por su lado. He citado un texto que parece inofensivo, pero que es de junio de 1848, cuando la revolución, aparecido en un periódico llamado Le Tocsin des travailleurs, y que no es nada. Significa que esta breve e inocua descripción describe el tipo de experiencias individuales, que pueden compartirse, que hacen que algo pueda constituirse como una voz para los obreros, lo cual no es eso de "los trabajadores nos juntamos y gritamos desde los tejados nuestras desgracias, etc." No. Esto significa: "Se construye una capacidad colectiva de decir, sobre la base de una transformación de nuestra relación con nuestra condición".
El resto de la entrevista en la Revue internationale des livres et des idées

the Programming Historian, parte V

Seguimos con la traducción de algunos capítulos del libro The Programming Historian, de William J. Turkel, Adam Crymble y Alan MacEachern.
Ahora vamos con el capítulo 6.

Salida en HTML

Poniendo la nueva información donde pueda usarse.

Ya aprendimos a usar Python para bajar documentos online y extraer información de ellos de modo automático. Recuerde que nuestro último objetivo es incorporar discretamente la programación en nuestra práctica histórica. Puesto que ya utiliza Firefox y Zotero para hallar y mantener sus recursos sería lógico que usara dichos programas para mantener la nueva información que obtengamos. La forma más fácil de hacerlo es hacer que sus programas en Python graben páginas web en su computadora, que puedan ser leídas en Firefox e indexadas y anotadas con Zotero. Vamos a hacer eso ahora, comenzando con una discusión sobre algunas cosas más que podemos hacer con cadenas en Python.

Formateando cadenas en Python

Python incluye un operador especial de formateo que le permite interpolar una cadena en otra. Está representado por el signo de porcentaje. Abra una sesión de Python y pruebe los siguientes ejemplos:

frame = 'Esto es un %s'
print frame
-> Esto es un %s
 
print frame % 'gato'
-> Esto es un gato
 
print frame % 'perro'
-> Esto es un perro

También hay un modo para interpolar una lista de cadenas en otra cadena:

frame2 = 'Estos son %s y %s'
print frame2
-> Estos son %s y %s
 
print frame2 % ('gatos', 'perros')
-> Estos son gatos y perros

En estos ejemplos, un %s en una cadena indica que otra cadena deberá incrustarse en ese lugar. Hay otros códigos de formateo de cadenas que nos permiten insertar números en cadenas en distintos formatos, como %i para enteros, %f para decimales de punto flotante, y así. Después seguiremos con ese tema.

Creando HTML

Una de las más poderosas ideas en informática es que algo que es código desde una perspectiva puede ser visto como dato desde otra. Esto es posible, en otras palabras, al escribir programas para manipular otros programas. El intérprete Python es un ejemplo. Lo que vamos a hacer ahora es combinar archivos de Python, cadenas de varios renglones, y simples etiquetas HTML para crear un programa en Python que cree archivos HTML de salida. Observe que escribimos un archivo con extensión .html en lugar de .txt.

# escribir-html.py
 
f = open('holamundo.html','w')
 
mensaje = """<html>
<head></head>
<body>Hola Mundo!</body>
</html>"""
 
f.write(mensaje)
f.close()

Guarde este programa como escribir-html.py y ejecútelo. Use File->Open->File en el Komodo para abrir holamundo.html y verificar que su programa haya creado el archivo. Esto se verá así:

pythont
"Hola Mundo" HTML generado por un programa en Python

Ahora vaya al browser Firefox y elija File->New Tab, vaya a la solapa y elija File->Abrir archivo. Seleccione holamundo.html. Ahora puede ver el mensaje en el browser.

Enviando HTML al Firefox

Creamos automáticamente un archive HTML pero tenemos que salir del Komodo e ir al Firefox para abrir el archivo en una nueva solapa. ¿No sería bueno que nuestro programa en Python incluyera este último paso? Ingrese el siguiente código y guárdelo como escribir-hmtl-2.py. Cuando lo ejecute, creará su archivo HMTL y luego automáticamente lo abrirá en una nueva solapa del Firefox.

# escribir-hmtl-2.py 
 
import webbrowser
 
f = open('holamundo.html','w')
 
mensaje = """<html>
<head></head>
<body>Hola Mundo!</body>
</html>"""
 
f.write(mensaje)
f.close()
 
webbrowser.open_new_tab('holamundo.html')
[Algunas personas no pudieron ejecutar el programa: más sobre el tema en la solapa discussion del wiki.]

Autodocumentar archivos de datos

La distinción entre data y metadata es crucial para las ciencias de la información. Metadatos son datos sobre datos. El concepto puede ser muy familiar para Ud., aún si nunca escuchó antes el término. Considere un libro tradicional. Si tomamos el texto del libro como data, hay varias características que están asociadas a ese texto pero que pueden o no estar explícitamente impresas en el libro. El título del trabajo, el autor, la editorial y el lugar y la fecha de la publicación son metadatos que generalmente están impresos en el libro. El lugar y fecha de la escritura, el nombre del editor, la ubicación del libro en el catálogo de la Biblioteca del Congreso, y el nombre de la fuente usada en el diseño a veces se incluyen en libro. La persona que compró un libro, puede o no escribir su nombre en las primeras páginas. Si el libro pertenece a la colección de una biblioteca, dicha biblioteca puede agregar metadatos adicionales, y sólo algunos de estos pueden estar físicamente ligados al libro. El registro de préstamo, por ejemplo, usualmente se lleva en una base de datos de algún tipo y se relaciona con el libro a través de un identificador único. Bibliotecas, archivos y museos mantienen, todos ellos, sistemas automáticos para generar y mantener esos metadatos.
Si usted trabaja con datos digitales, es una buena idea incorporar metadatos en sus archivos cuando sea posible. En secciones posteriores trabajaremos con el Extensible Markup Language (XML), que es ideal para ese propósito. Por ahora, no obstante, necesitaremos desarrollar unas pocas estrategias para autodocumentar nuestos archivos de datos.

Comentarios en Python

Ya vimos un ejemplo de esto. En Python, cualquier línea que comience con una almohadilla (#) es reconocida como comentario y es ignorada por el intérprete Python. Los comentarios se hacen con la intención de permitir a los programadores comunicarse entre sí. En buena medida, los programas mismos están escritos y formateados de manera que permita la comunicación entre programadores. Los códigos que están cerca de los requerimientos de una máquina son conocidos como lenguajes de bajo nivel y los que están cerca del lenguaje natural son conocidos como de alto nivel. Uno de los beneficios de usar un lenguaje como Python es que es de muy alto nivel, lo que hace muy fácil la comunicación entre nosotros y usted (con su respectivo costo en términos de eficiencia computacional).

Construyendo un “wrapper” para HTML

Ya aprendimos cómo incrustar un mensaje como “Hola mundo” en etiquetas HTML, escribir el resultar en un archivo y abrirlo automáticamente en el browser. Un programa que pone código de formato en un texto utilizado por otro programa es un wrapper. Lo que vamos a hacer ahora es desarrollar un wrapper para HTML, para la salida de nuestro código que computa las frecuencias de palabras.
Juntemos parte de los códigos que ya escribimos en algunas funciones. Una de ellas, a partir de una URL, retornaba una cadena de texto en minúsculas desde una página web. Copie esto en el módulo dh.py.

# Dada una URL, retorne una cadena en minúsculas desde la página.
 
def webPageToText(url):
    import urllib2
    response = urllib2.urlopen(url)
    html = response.read()
    texto = stripTags(html).replace('&nbsp;', ' ')
    return texto.lower()

También queremos una función que tome una cadena de cualquier clase y la ponga en el cuerpo de un archivo HTML, el cual será visualizado en Firefox inmediatamente. Este función puede incluir algunos metadatos básicos, como la hora y la fecha en que fue creado el archivo, así como el nombre del programa que lo creó. Estudie atentamente el siguiente código, luego cópielo en el módulo dh.py.

# Dados un nombre de programa desde el cual se llama a la función, una # URL y una cadena para wrapear,
# genera una cadena en el cuerpo de un archivo HTML con metadatos 
# básicos, y la abre en una ventana de Firefox.
 
def wrapStringInHTML(programa, url, body):
    import datetime
    from webbrowser import open_new_tab
    ahora = datetime.datetime.today().strftime("%Y%m%d-%H%M%S")
    filename = programa + '.html'
    f = open(filename,'w')
    wrapper = """<html>
        <head>
        <title>%s output - %s</title>
        </head>
        <body><p>URL: <a href=\"%s\">%s</a></p><p>%s</p></body>
        </html>"""
    whole = wrapper % (programa, ahora, url, url, body)
    f.write(whole)
    f.close()   
    open_new_tab(filename)

Observe que esta función hace uso de un operador de formato de cadena que ya mencionamos. Es ese operador el que llama a la biblioteca Python denominada datetime para determinar la fecha y hora actual. Este metadato, junto con el nombre del programa que llama a la función, es guardado en la etiqueta título (title) del HTML. El archivo HTML que es creado tiene el mismo nombre que el programa Python que lo crea pero con una extensión .html en lugar de una .py.

Poniendo todo junto

Ahora vamos a crear otra versión de nuestro programa para computar frecuencias. En lugar de enviar los resultados al panel de salido del Komodo, los enviaremos a un archivo HTML que será abierto en una nueva pestaña del Firefox. Desde ahí, los resultados pueden ser agregados fácilmente a Zotero. Copie el siguiente código en el Komodo, guárdelo como html-to-freq-3.py y ejecútelo para confirmar que el programa trabaja como esperamos.

# html-to-freq-3.py
 
import dh
 
# crea un diccionario ordenado de pares de palabra-frecuencia.
url = 'http://niche.uwo.ca/programming-historian/dcb/dcb-34298.html'
texto = dh.webPageToText(url)
fullwordlist = dh.stripNonAlphaNum(texto)
wordlist = dh.removeStopwords(fullwordlist, dh.stopwords)
dictionary = dh.wordListToFreqDict(wordlist)
sorteddict = dh.sortFreqDict(dictionary)
 
# compila el diccionario en una cadena y le agrega los 
# metadatos de HTML.
 
outstring = ""
for s in sorteddict:
    outstring += str(s)
    outstring += "<br />"
dh.wrapStringInHTML("html-to-freq-3", url, outstring)

Fíjese que entremezclamos nuestros pares de palabra-frecuencia con la etiqueta HTML llamada break, la que genera una nueva línea. Si todo va bien, usted podrá ver las mismas frecuencias de palabras que computamos en la última sección.

Utilizando frecuencias de palabras para refinar una búsqueda en Google

Agreguemos un giro más de sofisticación. Comenzamos con una búsqueda en Google de “dollard” y contamos el número de “hits” en las primeras cinco páginas que actualmente refieren a Adam Dollard Des Ormeaux. Cuando nosotros [los autores] probamos esto era 7/01/2008, y terminamos con 3 de 50 o 6% del total.
Ahora vamos a hacer una búsqueda de "dollard iroquois long sault enemy" y contamos el número de “hits” que refieren a Adam Dollard Des Ormeaux. Cuando probamos esto el 7 de enero de 2008, tuvimos 50 sobre 50 o 100%. Estas últimas palabras que usamos son características del texto, y podemos fácilmente hallar otras como ellas. ¿No sería bueno hacerlo automáticamente?
Observe la URL de la búsqueda de Google que hicimos. Comienza con algo así:

http://www.google.com/search?q=dollard+iroquois+long+sault+enemy

Supongamos que queremos hacer un número pequeño de estas consultas. Si tomamos los n términos más altos en nuestra lista de frecuencias de palabras, podemos construir una consulta como esa automáticamente y hacer un link para cada página formateada con los resultados.
La forma básica del hyperlink en HTML es

<a href="URL">NombreDelLink</a>

Queremos hacer automáticamente la URL para la búsqueda de Google y debemos incrustrar esa URL en una etiqueta a de HTML como la de arriba. Estudie con atención la siguiente función y agréguela en el módulo dh.py.

# Dada una lista palabras y un nombre de link, devuelve
# un link a un archive HTML con una búsqueda de Google para la lista.
 
def keywordListToGoogleSearchLink(keywords, linkname):
    gsearch = '<a style=\"text-decoration:none\" '
    gsearch += 'href=\"http://www.google.com/search?q='
    gsearch += '+'.join(keywords)
    gsearch += '\">'
    gsearch += linkname
    gsearch += '</a>'
    return gsearch

Fíjese que agregamos algunas líneas de CSS a la etiqueta a del HTML para prevenir que el browser subraye automáticamente el hyperlink. Aprenderemos más sobre CSS (Cascading Style Sheets) más tarde; por ahora sólo haremos las salidas de los próximos programas que escribamos resulten más legibles.

(hay una cosa en este código que es contraintuitiva. Para crear una cadena desde la lista, llamamos al método join para utilizar el delimitador que queremos entre los elementos de la lista. El delimitador es un signo más (+) en nuestro caso ya que estamos construyendo una cadena de consulta de una URL. Mucha gente da por sentado que join es un método de listas pero no es así.)
Puede probar la function en una sesión del intérprete Python si quiere. Cópiela y péguela en Python y ejecútela. Luego, puede hacer lo siguiente:

testwords = ('this', 'is', 'a', 'test')
print keywordListToGoogleSearchLink(testwords, "Do Google Search")
-> <a style="text-decoration:none" 
      href="http://www.google.com/search?q=this+is+a+test">Do Google Search</a>

Ahora puede revisar nuestro código para incluir nuestro búsqueda automática y creador de links. Copie el siguiente código en el Komodo, guárdelo como html-to-freq-4.py y ejecútelo.

# html-to-freq-4.py
 
import dh
 
# crea un diccionario ordenado de pares de frecuencia-palabras
 
url = 'http://niche.uwo.ca/programming-historian/dcb/dcb-34298.html'
texto = dh.webPageToText(url)
fullwordlist = dh.stripNonAlphaNum(texto)
wordlist = dh.removeStopwords(fullwordlist, dh.stopwords)
dictionary = dh.wordListToFreqDict(wordlist)
sorteddict = dh.sortFreqDict(dictionary)
 
# crea el link de búsqueda en Google.
keywords = []
for k in sorteddict[0:5]:
    keywords.append(str(k[1]))
gsearch = dh.keywordListToGoogleSearchLink(keywords, 'Google Search n=5')
 
# compila el diccionario en una cadena y en un HTML con datos.
outstring = gsearch + "<br /><br />"
for s in sorteddict:
    outstring += str(s)
    outstring += "<br />"
dh.wrapStringInHTML("html-to-freq-4", url, outstring)

Cuando pruebe este programa, verá que hay un hyperlink en la salida que puede clickear para enviar la búsqueda refinada a Google. Como un ejercicio, trate de modificar su script para procesar la biografía del explorador Pierre-Esprit Radisson (1640-1710). Podrá ver que las búsquedas generadas automáticamente harán más fácil hallar contenido relevante para su trabajo.

los que susurran

Orlando Figes. Los que susurran. La represión en la Rusia de Stalin, Edhasa, 2009, 959 páginas.
Figes, Los que susurran

Los que susurran… es un libro sobre hombres y mujeres que sufrieron, de una manera u otra, persecuciones en la Unión Soviética. Decir que se trata de crímenes del estalinismo sería quedarse cortos, porque tras la muerte de Stalin, el mundo secreto del susurro, el miedo, el desarraigo, el trauma, persisitieron. Si bien en el libro algunas biografías se destacan (como la de Konstantin Simonov, por ejemplo), el protagonismo se lo lleva el numeroso cuerpo de pequeñas biografías o biografemas, concebido a partir de archivos y entrevistas orales. El libro trata sobre la rusia de Stalin y se concentra en el largo período que va desde fines de los años veinte (con centro en el proceso conocido como deskulakización) hasta el llamado deshielo (con centro en el discurso de Kruschev en el XX congreso del PCUS sobre los crímenes de Stalin). Las grandes purgas de los años treinta y el impacto de la guerra en el ecosistema soviético son otros dos grandes hitos en el relato.
En este blog ya se han dicho algunas cosas sobre Orlando Figes. Anaclet Pons escribió un post sobre este mismo texto en el que por encima de la novedad de Los que susurran… se hacía referencia al debate acerca de la historiografía liberal y la escritura de la historia soviética en tiempos post-stalinistas o postmodernos o postparanoicos, como se prefiera. Los comentarios al post (escritos por Nicolás Pereyra y por Nes) ensayaron sendos intentos por cuestionar la escritura de Figes precisamente por su "liberalismo".
Después de leer el libro puedo opinar sobre el asunto del liberalismo de Figes (antes leí otros libros suyos, los que me gustaron y a los que ahora percibo desde otro perspectiva). Los que susurran… tiene el mismo ritmo que Anaclet Pons recuperó en su cita del comienzo del libro en el post referido. El historiador forja bisagras entre distintos relatos de familias purgadas, individuos arrojados a los campos, desposeídos, desterritorializados. Esos relatos se anidan en torno al trauma, no sólo en torno a los acontecimientos jurídicos o policiales que estuvieron en el centro de cada uno de esas pequeñas historias; es así como también leemos sobre el impacto de esos hechos, sobre la cotidianidad de los que quedaron, sobre la desestructuración de las familias a las que le han sido arrebatados uno, dos, tres miembros. Figes es un gran historiador y se mueve entre esos materiales -muchos de los cuales se pueden consultar en orlandofiges.com- con notable pericia.
Se trata, sin embargo, de una narración que hereda quizás demasiado de Archipiélado Gulag, un libro que con esa poética activó distintas reflexiones políticas cuando fue difundido. Exagerando, podría decirse que Los que susurran… es una versión del archipiélago, una mirada sobre los estragos del estalinismo en el corazón del domus, y a la vez una mirada que pretende liberarse del tono solzhenitzin, de la toma de partido. Pero al denunciar las incursiones del poder en el entramado civil a través de esa "reconstrucción" testimonial, Figes parece considerar al tejido civil naturalmente liberado de la política.
Por esas dos cosas es que, más o menos por la mitad de libro, me empecé a preguntar si esa estrategia narrativa que explota el testimonio para inducir una conclusión acerca del estalinismo in toto, finalmente no devenía un límite para los objetivos del texto. El libro no tiene el propósito de desarrollar esa red de trazas menores ni de salirse del archivo de casos para discutir "la rusia de Stalin". Así se sostiene hasta el final. Y eso se debe a que la razón que anima el armado del puzzle historiográfico, la lógica que escribe las bisagras, es anterior, es apriori. Y ese punto, que liga a Figes con El archipiélago… pero también a Figes con el "liberalismo" del que se le acusa, es algo que empieza a arruinar a esas voces inolvidables, que deteriora ese tejido hecho de penas e injusticias, porque al imponerles una causa externa (Stalin, los totalitarismos, etc.) menoscaba la lucha de esos hombres y mujeres por vivir el mapa kafkiano del poder pero también el del departamento comunal, el del pasillo, el del barrio poblado de "enemigos del pueblo", denunciantes, delatores, chicas del komsomol con padres kulaks, huérfanos, soplones, soplones soplados, relapsos, ascetas y vencidos. Al poner, Figes, esos testimonios como prueba de algo que se da por existente o de algo que se constituye casi exclusivamente a partir de la persecución de gentes, reduce cuantiosamente su archivo. Figes entiende claramente los problemas de la historia oral para dar cuenta de procesos históricos (aunque prefiere esos métodos al analisis de obras literarias) pero si tales inconvenientes caben en los complejos procedimientos de la memoria y el olvido, también nos llegan del cuestionario con el que se interpretan los dichos o gestos ajenos. El libro de Figes se hace cada vez menos complejo a medida que avanzamos en él debido precisamente a que la repetición de una estrategia casi judicial tiene como base una explicación alóctona (aunque con ella no pretenda exculpar).
Los que susurran… multiplica nuestras preguntas, abre zonas oscuras, litigios regionales entre el trauma y la felicidad. Nos muestra, Figes, pequeñas ventanas ominosas de una vida cotidiana que se parece un poco a las del lager pero más a la que conocemos. Nos las muestra un poco, digo, pero también las apaga, las somete a una explicación que no quiere saber nada de cada una de ellas. Es sobre ese desconcierto entre lo conocido y lo conocido ominoso sobre el que podemos operar mejor con libros como el de Richard Stites, Revolutionary Dreams… (incluso en su acendrado antiestalinismo) o el de Susan Buck Morss, Mundo Soñado y catástrofe… Una zona que tiene relación con el poder con mayúsculas pero no sólo porque lo padece, sino porque lo anima y es animada por él. El libro de Figes termina con un fragmento de una entrevista en donde alguien se enorgullece de poder decir su descendencia kulak. Se trata de una liberación, de una catarsis, pero en cierto modo se trata también de poner a esa figura como resistente, a la víctima como contradictor. Al devolverle una entidad política que a lo largo del libro el propio Figes le había negado (kulak era mayormente una figura de acusación, un modo conspirativo de extirpar a quienes tenían algunas posesiones o hablaban en voz alta sobre la realidad), Figes nos revela su enemigo y los límites del argumento que opone la libertad del individuo a los regímenes socialistas. Al menos los límites de esa oposición para abordar la pequeña dimensión, la cocina nimia de las micropolíticas.

the Programming Historian, parte IV

Seguimos con la traducción de algunos capítulos del libro The Programming Historian, de William J. Turkel, Adam Crymble y Alan MacEachern.
Ahora vamos con el capítulo 5.

Calculando frecuencias

Medidas usuales para textos

En la sección anterior, escribimos un programa en Python al que llamamos html-a-lista-1.py . Dicho programa sirve para bajar una página web a la que le quita el formateo HTML y los metadata, y luego nos devuelve una lista de “palabras”, como esta:

 ['Dictionary', 'of', 'Canadian', 'Biography', 'DOLLARD', 'DES', 
'ORMEAUX', '(called', 'Daulat', 'in', 'his', 'death', 'certificate', 
'and', 'Daulac', 'by', 'some', 'historians),', 'ADAM,', 'soldier,',
'\x93garrison', 'commander', 'of', 'the', 'fort', 'of', 
'Ville-Marie', '[Montreal]\x94;', 'b.', '1635,', 'killed', 'by', 
'the', 'Iroquois', 'at', 'the', 'Long', 'Sault', 'in', 
'May&nbsp;1660.', '\xa0\xa0\xa0\xa0\xa0', 'Nothing', 'is', 'known', 
'of', 'Dollard\x92s', 'activities', 'prior', 'to', 'his', 'arrival', 
'in', 'Canada', 'except', 'that', '\x93he', 'had', 'held', 'some', 
'commands', 'in', 'the', 'armies', 'of', 'France.\x94', 'Having', 
'come', 'to', 'Montreal', 'as', 'a', 'volunteer,', 'very', 
'probably', 'in', '1658,', 'he', 'continued', 'his', 'military', 
'career', 'there.', 'In', '1659', 'and', '1660', 'he', 'was', 
'described', 'as', 'an', '\x93officer\x94', 'or', '\x93garrison', 
'commander', 'of', 'the', 'fort', 'of', 'Ville-Marie,\x94', 'a', 
'title', 'that', 'he', 'shared', 'with', 'Pierre', 'Picot\xe9', 
'de', 'Belestre.', 'We', 'do', 'not', 'however', 'know', 'what', 
'his', 'particular', 'responsibility', 'was.']

Debido a que ya sabemos leer, esa habilidad del programa, por sí misma, no es muy importante. Pero podemos usar el texto para hacer cosas que usualmente no son posibles sin un software especializado. Vamos a empezar calculando las frecuencias de palabras y de otras unidades lingüísticas.

Limpiando la lista

Está claro que nuestra lista necesitará un poco de limpieza antes de que podamos usarla para contar frecuencias. Antes que nada, no queremos saber las frecuencias atadas a mayúsculas o minúsculas: “Dollard” y “DOLLARD” deberían ser contadas como la misma palabra. Normalmente las palabras son clasificadas en minúsculas cuando contamos frecuencias, por lo que está bien utilizar el método de cadena lower.

print('Hola MUNDO'.lower())
-> hola mundo

Hay distintas marcas de puntuación que nos cambiarían el conteo de frecuencia si las incluiríamos en él. Queremos que “soldado:” sea contabilizada como “soldado” y “[Montreal]” como “Montreal”. Mirando en la impresión en el panel de salida del Komodo, encontramos también “&nbsp ;” que es el código HTML para el ampersand. Utilizando otro método de cadena, podemos reemplazar ese código con un espacio en blanco, de la siguiente manera:

print('hola&nbsp;mundo')
-> hola&nbsp;mundo
 
print('hola&nbsp;mundo'.replace('&nbsp;',' '))
-> hola mundo

Hay también un grupo de caracteres acentuados franceses que son representados con cadenas Unicode como “\xe9” (que indica “é”). Aprenderemos más acerca de trabajar con caracteres Unicode más tarde; por ahora vamos a dejarlos como están.
En este punto, podríamos mirar en otras entradas DCB [de ese diccionario se extrajo la página web del ejemplo] y en un rango más amplio de potenciales fuentes de documentos para asegurarnos que no haya otros caracteres especiales que nos traigan problemas más adelante. Podríamos también anticipar situaciones donde no queremos quitar la puntuación (por ejemplo, el signo que distingue un monto de dinero como en “$1629” de un año, o el que distingue el sentido de “1629-40” del otro en “1629 40”). Esto es lo que hace que los programadores profesionales cobren: tratar de pensar todo lo que puede estar mal por adelantado.

Vamos a encarar otra aproximación. Nuestro principal objetivo es desarrollar técnicas que un historiador o una historiadora puedan utilizar durante su investigación. Esto significa que siempre vamos a preferir la solución correcta que pueda desarrollarse rápidamente. Más que dedicar tiempo a hacer nuestro programa robusto frente a excepciones, simplemente vamos a descartar todo aquello que no sea una letra acentuada o sin acentuar o un número arábigo. La programación es normalmente un proceso de refinamiento por etapas. Comenzamos con un problema y con una solución parcial, y entonces procedemos a refinar nuestra solución hasta hacer algo que funcione mejor.

Nuestro primer uso de expresiones regulares.
A los efectos de eliminar caracteres especiales, vamos a hacer uso de un poderoso mecanismo llamado expresiones regulares. Las expresiones regulares son facilitadas por muchos lenguajes de programación de distintas maneras. Para hacer lo que queremos ahora, tenemos que importar la biblioteca de expresiones regulares de Python y compilar un patrón que encuentre cualquier cosa que no sea un carácter alfanumérico. Copie la siguiente función y péguela en el módulo dh.py.

# Dada una cadena de texto, remueva todos los caracteres alfanuméricos
# (utilizando la definición Unicode de alfanumérico).
 
def stripNonAlphaNum(texto):
    import re
    return re.compile(r'\W+', re.UNICODE).split(texto)

La expresión regular en el código de más arriba es \W+. La \W es la forma abreviada para significar la clase de caracteres alfanuméricos. En las expresiones regulares de Python, el signo más (+) encuentra una o más copias de un caracter determinado. El re.UNICODE le dice al intérprete que queremos incluir caracteres de otros idiomas en nuestra definición de alfanumérico, además de las series que van de la A a la Z, de la a a la z, y del / al 9 [N.T: el primer set de caracteres ASCII era etnocéntrico y no incluía signos como las vocales acentuadas o la cedilla; en el texto original las series enumeradas al final de la última oración son del inglés; y todo lo que queda fuera, parte de “los otros idiomas del mundo”]. Las expresiones regulares deben ser compiladas antes de ser usadas, que es lo que el resto de las órdenes del programa hace. No se preocupe por entender el resto de la compilación por ahora.
Al refinar nuestro programa html-a-lista, podemos dejarlo así:

# html-a-lista-2.py
 
import urllib2
import dh
 
url = 'http://niche.uwo.ca/programming-historian/dcb/dcb-34298.html'
 
response = urllib2.urlopen(url)
html = response.read()
texto = dh.stripTags(html).replace('&nbsp;', ' ')
wordlist = dh.stripNonAlphaNum(texto.lower())
print wordlist[0:500]

Cuando ejecute el programa y mire el panel de salida del Komodo, podrá ver que ha hecho un mejor trabajo. Como esperábamos, dejó los caracteres acentuados en forma de códigos (así, palabras como “Picoté” aparecen como “picot\xe9”). Dividió los términos con guiones, como “Ville-Marie” en dos palabras, y cambió el posesivo “s” en una palabra separada, dejando fuera el apóstrofo. Esta es una buena aproximación a lo que queríamos hacer, así que podemos avanzar a contar frecuencias antes de intentar hacer este programa mejor. (Si usted trabaja con fuentes en más de un idioma necesitará aprender más acerca del estándar Unicode y acerca del soporte de Python para ese estándar.

Diccionarios de Python

Tanto las cadenas como las listas están secuencialmente ordenadas, lo que quiere decir que podemos acceder a sus contenidos utilizando un index, un número que comienza con 0. Si tiene una lista que contiene cadenas, puede usar un par de índices para acceder, primero, a una cadena en particular, y luego a un caracter específico en esa cadena. Estudie el siguiente ejemplo:

s = 'hola mundo'
print s[0]
-> h
 
print s[1]
-> o
 
m = ['hola', 'mundo']
print m[0]
-> hola
 
print m[1]
-> mundo
 
print m[0][1]
-> o
 
print m[1][0]
-> m

Para llevar la cuenta de las frecuencias, necesitaremos otro tipo de objeto en Python, un diccionario. El diccionario es una colección desordenada de objetos. Esto significa que no podemos usar un índice para recuperar un elemento del mismo. Podemos hacerlo, de todos modos, utilizando una clave (key). Estudie el siguiente ejemplo:

d = {'mundo': 1, 'hola': 0}
print d['hola']
-> 0
 
print d['mundo']
-> 1
 
print d.keys()
-> ['mundo', 'hola']

Fíjese que usamos llaves para definir un diccionario pero corchetes para acceder a las cosas que hay en él. Las operaciones con claves devuelven una lista de claves que están definidas en el diccionario.

Conteo de frecuencia de palabras

Ahora vamos a contar la frecuencia de cada palabra en nuestra lista. Ya vimos que esto es fácil procesar una lista utilizando un bucle for. Pruebe guardando y ejecutando este ejemplo:

# contar-lista-items-1.py
 
wordstring = 'quien mal anda mal acaba '
wordstring += 'dime con quien andas y te dire quien eres'
 
wordlist = wordstring.split()
 
wordfreq = []
for word in wordlist:
    wordfreq.append(wordlist.count(word))
 
print "Cadena\n" + wordstring +"\n"
print "Lista\n" + str(wordlist) + "\n"
print "Frecuencia\n" + str(wordfreq) + "\n"
print "Pares\n" + str(zip(wordlist, wordfreq))

Obtendrá algo como esto:

Cadena
quien mal anda mal acaba dime con quien andas y te dire quien eres
Lista
['quien', 'mal', 'anda', 'mal', 'acaba', 'dime', 'con', 'quien', 'andas', 'y', 'te', 'dire', 'quien', 'eres']
Frecuencia
[3, 2, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1]
Pares
[('quien', 3), ('mal', 2), ('anda', 1), ('mal', 2), ('acaba', 1), ('dime', 1), ('con', 1), ('quien', 3), ('andas', 1), ('y', 1), ('te', 1), ('dire', 1), ('quien', 3), ('eres', 1)]

En ese programa, empezamos con una cadena y la dividimos en una lista, como ya lo habíamos hecho antes. Entonces recorrimos cada palabra de esa lista y contamos las veces que esa palabra aparece en toda la lista. Luego agregamos el resultado a una lista de frecuencias de palabras. Usando el comando zip podemos comparar la primera palabra de la lista de palabras con el primer número de la lista de frecuencias, la segunda palabra con la segunda frecuencia y así sucesivamente. Finalizamos obteniendo una lista de pares (palabras y frecuencias). La declaración str convierte cualquier objeto a una cadena, para poder imprimirlo.
Python incluye una herramienta muy conveniente llamada lista comprensiva (list comprehension), que podemos usar para hacer lo mismo que con el bucle loop pero más económicamente.

# contar-lista-items-2.py
wordstring = 'quien mal anda mal acaba '
wordstring += 'dime con quien andas y te dire quien eres'
wordlist = wordstring.split()
wordfreq = [wordlist.count(w) for w in wordlist]
print "Cadena\n" + wordstring +"\n"
print "Lista\n" + str(wordlist) + "\n"
print "Frecuencias\n" + str(wordfreq) + "\n"
print "Pares\n" + str(zip(wordlist, wordfreq))

En este punto tenemos una lista de pares, donde cada par contiene una palabra y su frecuencia. Note que esta lista podría ser redundante. Si el artículo “el” se repitiera 500 veces, la lista contendría quinientas copias de ese par (‘el’, 500). La lista está, además, ordenada por el orden de las palabras en el texto inicial. Podemos resolver ambos problemas convirtiéndola en un diccionario. Entonces todo lo que tenemos que hacer es imprimir el diccionario en orden, desde los ítems más frecuentes a los menos frecuentes.

De HTML a un diccionario de pares palabra-frecuencia.

A partir de lo que tenemos hasta ahora, queremos una función que pueda convertir una lista de palabras en un diccionario de pares de palabra-frecuencia. La única declaración nueva que necesitamos conocer es dict, que hacer un diccionario a partir de una lista de pares. Agregue el siguiente código al módulo dh.py.

# Dada una lista de palabras, devuelva un diccionario de
# pares de palabra-frecuencia.
 
def wordListToFreqDict(wordlist):
    wordfreq = [wordlist.count(p) for p in wordlist]
    return dict(zip(wordlist,wordfreq))

Vamos a querer además un función que pueda ordenar un diccionario de pares de palabra-frecuencia por frecuencias, de modo descendiente. Copie también esto al módulo dh.py:

# Ordenar un diccionario de pares de palabra-frecuencia por
# frecuencias de modo descendiente
 
def sortFreqDict(freqdict):
    aux = [(freqdict[key], key) for key in freqdict]
    aux.sort()
    aux.reverse()
    return aux

Podemos ahora escribir un programa que tome una URL y devuelva pares de palabras-frecuencia para la página web, ordenados de acuerdo a la frecuencia de cada palabra, desde la que más tiene a la que menos tiene. Copie el siguiente programa en el Komodo, guarde como html-to-freq.py y ejecútelo. Estudie cuidadosamente el programa y lo que se imprime en el panel de salida, antes de continuar.

# html-a-freq.py
 
import urllib2
import dh
 
url = 'http://niche.uwo.ca/programming-historian/dcb/dcb-34298.html'
 
response = urllib2.urlopen(url)
html = response.read()
text = dh.stripTags(html).replace('&nbsp;', ' ')
wordlist = dh.stripNonAlphaNum(text.lower())
dictionary = dh.wordListToFreqDict(wordlist)
sorteddict = dh.sortFreqDict(dictionary)
for s in sorteddict: print str(s)

Removiendo las stop words

Cuando miramos la salida de nuestro programa html-a-freq.py, vemos que las mayores frecuencias son para palabras como “the”, “of”, “and”.

(647, 'the')
(310, 'of')
(273, 'to')
(202, 'and')
(171, 'in')
(134, 'a')
(118, 'that')
(91, 'dollard')
(78, 'was')
(78, 'their')
(75, 'were')
(72, 'they')
(71, 'his')

Esas palabras son las más usuales en cualquier texto en inglés, y no nos dicen mucho sobre la biografía de Dollard. En general, estamos más interesados en encontrar las palabras que nos permitan distinguir este texto de otros con diferentes temas. Por lo que vamos a filtrar, a quitar, las palabras más comunes. Las palabras que son ignoradas, como esas, se conocen como stop words. Vamos a usar una lista, adaptada de un post de unos cientistas de Glasgow. Copie lo siguiente en el comienzo de la biblioteca dh.py.

stopwords = ['a', 'about', 'above', 'across', 'after', 'afterwards']
stopwords += ['again', 'against', 'all', 'almost', 'alone', 'along']
stopwords += ['already', 'also', 'although', 'always', 'am', 'among']
stopwords += ['amongst', 'amoungst', 'amount', 'an', 'and', 'another']
stopwords += ['any', 'anyhow', 'anyone', 'anything', 'anyway', 'anywhere']
stopwords += ['are', 'around', 'as', 'at', 'back', 'be', 'became']
stopwords += ['because', 'become', 'becomes', 'becoming', 'been']
stopwords += ['before', 'beforehand', 'behind', 'being', 'below']
stopwords += ['beside', 'besides', 'between', 'beyond', 'bill', 'both']
stopwords += ['bottom', 'but', 'by', 'call', 'can', 'cannot', 'cant']
stopwords += ['co', 'computer', 'con', 'could', 'couldnt', 'cry', 'de']
stopwords += ['describe', 'detail', 'did', 'do', 'done', 'down', 'due']
stopwords += ['during', 'each', 'eg', 'eight', 'either', 'eleven', 'else']
stopwords += ['elsewhere', 'empty', 'enough', 'etc', 'even', 'ever']
stopwords += ['every', 'everyone', 'everything', 'everywhere', 'except']
stopwords += ['few', 'fifteen', 'fifty', 'fill', 'find', 'fire', 'first']
stopwords += ['five', 'for', 'former', 'formerly', 'forty', 'found']
stopwords += ['four', 'from', 'front', 'full', 'further', 'get', 'give']
stopwords += ['go', 'had', 'has', 'hasnt', 'have', 'he', 'hence', 'her']
stopwords += ['here', 'hereafter', 'hereby', 'herein', 'hereupon', 'hers']
stopwords += ['herself', 'him', 'himself', 'his', 'how', 'however']
stopwords += ['hundred', 'i', 'ie', 'if', 'in', 'inc', 'indeed']
stopwords += ['interest', 'into', 'is', 'it', 'its', 'itself', 'keep']
stopwords += ['last', 'latter', 'latterly', 'least', 'less', 'ltd', 'made']
stopwords += ['many', 'may', 'me', 'meanwhile', 'might', 'mill', 'mine']
stopwords += ['more', 'moreover', 'most', 'mostly', 'move', 'much']
stopwords += ['must', 'my', 'myself', 'name', 'namely', 'neither', 'never']
stopwords += ['nevertheless', 'next', 'nine', 'no', 'nobody', 'none']
stopwords += ['noone', 'nor', 'not', 'nothing', 'now', 'nowhere', 'of']
stopwords += ['off', 'often', 'on','once', 'one', 'only', 'onto', 'or']
stopwords += ['other', 'others', 'otherwise', 'our', 'ours', 'ourselves']
stopwords += ['out', 'over', 'own', 'part', 'per', 'perhaps', 'please']
stopwords += ['put', 'rather', 're', 's', 'same', 'see', 'seem', 'seemed']
stopwords += ['seeming', 'seems', 'serious', 'several', 'she', 'should']
stopwords += ['show', 'side', 'since', 'sincere', 'six', 'sixty', 'so']
stopwords += ['some', 'somehow', 'someone', 'something', 'sometime']
stopwords += ['sometimes', 'somewhere', 'still', 'such', 'system', 'take']
stopwords += ['ten', 'than', 'that', 'the', 'their', 'them', 'themselves']
stopwords += ['then', 'thence', 'there', 'thereafter', 'thereby']
stopwords += ['therefore', 'therein', 'thereupon', 'these', 'they']
stopwords += ['thick', 'thin', 'third', 'this', 'those', 'though', 'three']
stopwords += ['three', 'through', 'throughout', 'thru', 'thus', 'to']
stopwords += ['together', 'too', 'top', 'toward', 'towards', 'twelve']
stopwords += ['twenty', 'two', 'un', 'under', 'until', 'up', 'upon']
stopwords += ['us', 'very', 'via', 'was', 'we', 'well', 'were', 'what']
stopwords += ['whatever', 'when', 'whence', 'whenever', 'where']
stopwords += ['whereafter', 'whereas', 'whereby', 'wherein', 'whereupon']
stopwords += ['wherever', 'whether', 'which', 'while', 'whither', 'who']
stopwords += ['whoever', 'whole', 'whom', 'whose', 'why', 'will', 'with']
stopwords += ['within', 'without', 'would', 'yet', 'you', 'your']
stopwords += ['yours', 'yourself', 'yourselves']

Ahora que pusimos esas palabras en una lista es fácil utilizarlas. Copie esta función también en el módulo dh.py.

# Dada una lista de palabras remueva cualquiera 
# que figure en la lista de stop words.
 
def removeStopwords(wordlist, stopwords):
    return [w for w in wordlist if w not in stopwords]
[Para ampliar este tema ver la solapa discussion en el wiki]

Poniendo todo junto

Ahora tenemos todo lo que necesitamos para determinar las frecuencias de palabras en páginas web. Copie lo siguiente en el Komodo, guárdelo como html-a-freq-2.py y ejecútelo.

# html-to-freq-2.py
 
import urllib2
import dh
 
url = 'http://niche.uwo.ca/programming-historian/dcb/dcb-34298.html'
 
response = urllib2.urlopen(url)
html = response.read()
text = dh.stripTags(html).replace('&nbsp;', ' ')
fullwordlist = dh.stripNonAlphaNum(text.lower())
wordlist = dh.removeStopwords(fullwordlist, dh.stopwords)
dictionary = dh.wordListToFreqDict(wordlist)
sorteddict = dh.sortFreqDict(dictionary)
for s in sorteddict: print str(s)

Si todo va bien, la salida debería mostrar algo así:

(91, 'dollard')
(64, 'iroquois')
(33, 'long')
(27, 'sault')
(24, 'enemy')
(24, '1660′)
(20, 'time')
(20, 'seventeen')
(20, 'french')
(19, 'new')
(19, 'montreal')
(19, 'army')
(18, 'hurons')
(18, 'fort')
(17, 'france')
(15, 'men')
(14, 'marie')
(14, 'companions')