ERG::Code-2019-1

De {}
Aller à la navigation Aller à la recherche

Introduction

Ce cours est destiné aux étudiant.e.s de BAC2. Cette année, nous nous concentrons sur le rapport du numérique au texte. Les interactions textuelles avec les machines, le code générateur de poésie, le code en tant que poésie, le code secret, le code caché. Nous serons amenés à créer des poésies algorithmiques, des générateurs de textes, des machines à plagier, des bots twitter, des ordinateurs qui parlent. À travers différentes expérimentations menées en atelier, nous aborderons plusieurs langages de programmation, concepts informatiques et exemples dans les champs de l'art, du design, de l'histoire de l'informatique et autres.

Pages des étudiants

Cesar Schwartz

Simon Blondeau

Anaïs Lheureux

Hugo Gucciardo

Brigitte Coric

Maud Serradell

Antoine Bouillet

Chloé Doppagne

Lilo Joris

Max Farré-Vilalta

Noé Sabard

Justin Roger

Manon Sallé

Aurélien Muller

Séances

15/03/2020: schémas

Pour cette première session à distance, je vous propose de réaliser un schéma le plus détaillé possible de votre programme. En partant du principe que le programme sera hébergé sur un serveur et qu'il sera lancé toutes les 5 minutes, le schéma doit détailler chaque étape de son fonctionnement. Vous pouvez réaliser le schéma à la main ou via un logiciel de dessin ou de création de diagrammes (draw.io - https://app.diagrams.net/ -, http://asciiflow.com/, etc.).

02/03/2020: web scraping

Librairies Python

  • User agent :

('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0')


#!/usr/bin/python
# -*- coding: utf-8 -*-

import mechanize
import lxml.html as parser
import cssselect

#01. naviguer sur le site cible
### on déclare un browser
br = mechanize.Browser()

### on ajoute des infos sur le navigateur
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0')]

### on ignore la gestion des robots du serveur
br.set_handle_robots(False)

### on récupère le code source de la page
data = br.open('https://poesie.webnet.fr/lesgrandsclassiques/Authors/B', timeout=10)

#print(data.read())

#02. parser la source pour récupérer les liens
source = data.read()

#unicode_src = source.decode('utf-8', 'ignore')

tree = parser.fromstring(source)

##pour chaque objet de type selector déduit du sélecteur css
for selector in cssselect.parse('.author-list__link'):
    ##on convertit l'objet selector en xpath
    xpath_selector = cssselect.HTMLTranslator().selector_to_xpath(selector)
    ##pour chaque lien trouvé par ce xpath
    for link in tree.xpath(xpath_selector):
        print(link.get('href'))
        print(link.text_content())
#!/usr/bin/python
# -*- coding: utf-8 -*-

import mechanize
import lxml.html as parser
import cssselect
import random

def getHtmlTree(url):
    ### on récupère le code source de la page
    data = br.open(url, timeout=10)

    #print(data.read())

    #02. parser la source pour récupérer les liens
    source = data.read()

    #unicode_src = source.decode('utf-8', 'ignore')

    tree = parser.fromstring(source)

    return tree

def getRandomLink(url, cssSelector):
    tree = getHtmlTree(url)

    ##pour chaque objet de type selector déduit du sélecteur css
    for selector in cssselect.parse(cssSelector):
        ##on convertit l'objet selector en xpath
        xpath_selector = cssselect.HTMLTranslator().selector_to_xpath(selector)
        ##pour chaque lien trouvé par ce xpath
        links = tree.xpath(xpath_selector)
        
        return random.choice(links).get('href')



#01. naviguer sur le site cible
### on déclare un browser
br = mechanize.Browser()

### on ajoute des infos sur le navigateur
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0')]

### on ignore la gestion des robots du serveur
br.set_handle_robots(False)

link1 = getRandomLink('https://poesie.webnet.fr/lesgrandsclassiques/Authors/B', '.author-list__link')

#print('https://poesie.webnet.fr'+link1)

url = '%s%s' % ('https://poesie.webnet.fr', link1)

poemeurl = '%s%s' % ('https://poesie.webnet.fr', getRandomLink(url, '.author-list__link'))

poemeTree = getHtmlTree(poemeurl)

#.poem__content

for selector in cssselect.parse('.poem__content'):
    ##on convertit l'objet selector en xpath
    xpath_selector = cssselect.HTMLTranslator().selector_to_xpath(selector)
    ##pour chaque poème trouvé par ce xpath
    poems = poemeTree.xpath(xpath_selector)
    print(poems[0].text_content())

    #print(poem.text_content())

09/02/2020: writing bot - Twitter API

  • Créer un compte Twitter (https://twitter.com/)
  • Convertir le compte en compte développeur (https://developer.twitter.com/en/apps)
  • Attendre la validation de la conversion par Twitter
  • Si Twitter envoie un mail demandant des précisions, répondre au mail.
  • Une fois le compte validé, aller à nouveau sur https://developer.twitter.com et cliquer sur "créer une app".
  • Générer les clés "access token" et "access token secret"
  • Enregistrer les 4 clés "consumer API", "consumer API secret", "access token" et "access token secret".

Voir https://help.twitter.com/en/rules-and-policies/twitter-automation pour les règles de Twitter


http://docs.tweepy.org/en/latest/

from credentials import *
import tweepy

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

'''
tweet = 'Tu veux un camembert?'
api.update_status(status=tweet)
'''
'''
for tweet in tweepy.Cursor(api.search, q='camembert', tweet_mode="extended").items(10):
    print(tweet.full_text)
'''
'''for tweet in tweepy.Cursor(api.user_timeline, '@Lagarde').items(10):
    print(tweet.text)'''

03/01/2020: writing bot: introduction

À propos de robots qui génèrent du texte.

Imaginer un robot qui intervient en postant du texte sur un ou plusieurs réseaux sociaux; mastodon, youtube, instagram, facebook, twitter, etc. Écrire une description de ce robot et la poster sur le wiki. La description doit répondre aux questions suivantes: - quelle(s) source(s) pour le texte - quels types de traitements sont utilisés pour générer le texte (penser aux traitements développés pendant le premier quadri) - qu'est-ce qui déclenche le post? - quel canal est utilisé pour le post?

@everyword, Allison Parrish: https://twitter.com/everyword

@nicetipsbot, Thricedotted: https://twitter.com/nice_tips_bot

@tinycarebot, Jonny Sun: https://twitter.com/tinycarebot

@infinite_scream, Nora Reed: https://twitter.com/infinite_scream

Darius Kazemi: http://tinysubversions.com/projects/

@predartbot, Maria Roszkowska et Nicolas Maigret: http://artbot.space/

Des bots qui n'écrivent pas mais qui agissent sur le web

https://wwwwwwwwwwwwwwwwwwwwww.bitnik.org/r/

09/12/2019: intro html css to print

Projet pour la fin du quadri

À partir d'une sélection de poèmes générés via les programmes écrits jusqu'ici en python, faire une édition à la fois en ligne et en print. La version en ligne doit être uploadée sur le serveur du cours. La version papier sera présentée au dernier cours; le 16/12.

Intro html/css

Démo: [1]

04/11/2019: Python suite et fin + INTERNET

Dernier énoncé

Le programme demande à l'utilisateur le nombre de vers à générer.
Le programme génère autant de vers aléatoires que le nombre entré par l'utilisateur, à partir des mots du poème source et en utilisant la formule syntaxique "article + nom + complément + verbe" 

Une fois que ça marche deux améliorations possibles:
* accorder en genre et en nombre les phrases (ortographe inclusive ou non)
* avoir plusieurs formules syntaxiques et les choisir aléatoirement (ou selon une certaine logique) à chaque vers


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random

with open('poeme', 'r') as tete:
    poeme = tete.read()
    
article = ["la", "le", "Un", "Les" ]
nom = ["voiture", "pied", "ceval", "ame", "vie", "flux", "nuit", "ciel", "Je", "tout", "j'", "Il", "jour", "oiseaux"  ]
verbe = ["bouge", "crisse", "etait", "est", "suis", "aime", "saigne", "va", "leve", "chantent"]
complement = ["rose", "cosmique", "loin", "gris", "hauteur", "peu", "tot" ]

print("Combien de vers souhaites tu génerer?")

nombre = int(raw_input())

for compteur in range (0,nombre):
    print(random.choice(article) + " " + random.choice(nom)+ " " + random.choice(verbe)+ " " + random.choice(complement))

14/10/2019: écriture de programme Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-



#Un script qui suit l'idée du livre dont vous êtes le héros, avec des réponses OUI on NON. Ex: La voiture bouge OU le cheval rose? réponse:
#Le programme donne le choix entre le vers n°1 ou le vers n°3
#Selon le choix de l'utilisateur, il affiche le vers 1 et le vers 2 ou le vers 3 et le vers 4
#Le choix est gardé en mémoire pour afficher le poème résultant à la fin du script


#1 charger le poème dans une variable
with open('poeme', 'r') as tete:
    poeme = tete.read()



'''
La voiture bouge
Le pied crisse
Le ceval rose
Perdant son ame
Qu'etait la vie
Le flux cosmique
La nuit est loin,
Le ciel est gris
Je suis tombee
Tout en hauteur
5lK5J 8.21JsMc1Js
j'aime la nuit
Il saigne peu,
Et s'Vk va tot
Un jour se leve
Les oiseaux chantent
'''

print(poeme)


'''
       0                  1                  2               3                  4                  5                6                7
['La voiture bouge', 'Le pied crisse', 'Le ceval rose', 'La voiture bouge', 'Le pied crisse', 'Le ceval rose', 'Le pied crisse', 'Le ceval rose']
['v', 'o', 'i', 't', 'u', 'r', 'e']

'''

#2 décomposer le poème en lignes (et stocker le résultat dans un tableau)
lignes = poeme.splitlines()
'''
print("Choisissez entre ces deux vers:")
print(" Pour "+lignes[0]+" tapez 1")
print(" Pour "+lignes[2]+" tapez 2")

#choix = input()
choix = int(raw_input())

if(choix == 1):
    print(lignes[0])
    print(lignes[1])
else:
    print(lignes[2])
    print(lignes[3])



print("Choisissez entre ces deux vers:")
print(" Pour "+lignes[4]+" tapez 1")
print(" Pour "+lignes[6]+" tapez 2")

#choix = input()
choix = int(raw_input())

if(choix == 1):
    print(lignes[4])
    print(lignes[5])
else:
    print(lignes[6])
    print(lignes[7])
'''

reponses = ''

for compteur in range(0, len(lignes), 4):
    print("Choisissez entre ces deux vers:")
    print(" Pour "+lignes[compteur]+" tapez 1")
    print(" Pour "+lignes[compteur+2]+" tapez 2")
    #choix = input()
    choix = int(raw_input())
    if(choix == 1):
        reponses = reponses + str(choix)
        print(lignes[compteur])
        print(lignes[compteur + 1])
    else:
        reponses = reponses + str(choix)
        print(lignes[compteur + 2])
        print(lignes[compteur + 3])

#reponses = 1212
'''
0     1     2     3
1     2     1     2
0 1   6 7   8 9   14 15
'''



print(reponses)

for compteur in range(0, len(reponses)):
    choix = int(reponses[compteur])
    #on affiche les lignes correspondantes
    if(choix == 1):
        #print(lignes[0])
        #print(lignes[1])
        #print(lignes[4])
        #print(lignes[5])
        print(lignes[compteur * 4])
        print(lignes[compteur * 4 + 1])
    else:
        #print(lignes[2])
        #print(lignes[3])
        #print(lignes[6])
        #print(lignes[7])

        print(lignes[compteur * 4 + 2])
        print(lignes[compteur * 4 + 3])
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#Le script decidera quelle phrase va le mieux avec la personalité de l'utilisateur en fonction de sa ville de naissance (addition de la valeur de chaque lettre). Si la valeur numérique de la ville est plus grande que le nombre de phrases disponibles, le compteur 'recommence'. Si l'utilisateur veut connaitre son mot préféré, il peut le faire en fonction de son âge multiplié par sa ville.

import string
import unicodedata

#1 charger le poème dans une variable
with open('poeme', 'r') as tete:
    poeme = tete.read()

lignes = poeme.splitlines()



print("Où es-tu né(e)?")
#ville = input()
ville = raw_input()
ville = unicodedata.normalize('NFD', unicode(ville, 'utf-8')).encode('ascii', 'ignore')
ville = ville.lower()
asciiChars = list(string.ascii_lowercase)


'''
bruxelles
['a', 'b'...]


'''
nbreVille = 0

for compteur in range(0, len(ville)):
    searchLettre = ville[compteur]
    for compteur2 in range(0, len(asciiChars)):
        laLettreQuonRegarde = asciiChars[compteur2]
        if(laLettreQuonRegarde == searchLettre):
            nbreVille = nbreVille + compteur2
            break

'''
while nbreVille >= len(lignes):
    nouveauNombre = 0
    for compteur in range(0, len(str(nbrVille))):
        nouveauNombre = nouveauNombre + int(nbrVille[compteur])

    nbreVille = nouveauNombre
'''

nbreVille = nbreVille % len(ville)

print(lignes[nbreVille])

07/10/2019: introduction Python

Boucles et variables

#!/usr/bin/env python
#!python
# -*- coding: utf-8 -*-


'''
Un programme qui demande le prenom de l'utilisateur
dlkdsqjdsq
'''

print("Qui est-ce?")

#input()

bloup = raw_input()

'''

print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
print("Salut "+bloup)
'''
#boucle infinie
'''while True:
    print("Salut "+bloup)'''


#boucle while avec compteur
'''
compteur = 0
while compteur < 10:
    print("Salut "+bloup)
    compteur = compteur + 1
'''

#boucle for
'''
for compteur in range(0, 100):
    print("Salut "+bloup+" "+str(compteur))
'''
'''
 0   1   2   3   4   5
[L | i | o | n | e | l]
'''

#print(bloup[2])

#le nombre de cases (de caracteres) de la variable bloup
print(len(bloup))

Conditions

#!/usr/bin/env python
# coding: utf-8

'''
<
>
>=
<=
==
!=
'''



print("Quel est ton age?")
age = int(raw_input())

if age < 10:
    for compteur in range(0, age):
        print(compteur)
        if compteur == 5:
            print("déjà 5 ans!")
    print "Oh ben t'es tout petit"
elif age < 20:
    print("Oh ben t'es tout jeune")
elif age < 30:
    print("Oh ben t'es presque vieux")
else:
    print "Oh ben t'es tout vieux"



print("Tu vas mourir dans "+str(88 - age))

Exercice

Écrire un scénario de script python pour traiter le poème collectif; mettre ce scénario dans la page personnelle sur le wiki.

30/09/2019 :introduction langages

Poésie binaire: suite

1001100 1100001 1011111 1110110 1101111 1101001 1110100 1110101 1110010 1100101 1011111 1100010 1101111 1110101 1100111 1100101

1001100 1100101 1011111 1110000 1101001 1100101 1100100 1011111 1100011 1110010 1101001 1110011 1110011 1100101


1001100 1100101 0100000 1100011 1100101 1110110 1100001 1101100 0100000 1110010 1101111 1110011 1100101

1010000 1100101 1110010 1100100 1100001 1101110 1110100 0100000 1110011 1101111 1101110 0100000 1100001 1101101 1100101

1010001 1110101 0100111 1100101 1110100 1100001 1101001 1110100 0100000 1101100 1100001 0100000 1110110 1101001 1100101

1001100 1100101 0100000 1100110 1101100 1110101 1111000 0100000 1100011 1101111 1110011 1101101 1101001 1110001 1110101 1100101


1001100 1100001 0100000 1101110 1110101 1101001 1110100 0100000 1100101 1110011 1110100 0100000 1101100 1101111 1101001 1101110 0101100 

1001100 1100101 0100000 1100011 1101001 1100101 1101100 0100000 1100101 1110011 1110100 0100000 1100111 1110010 1101001 1110011

1010011 1101111 1110101 1110011 0100000 1101100 0100111 1101111 1100011 1100101 1100001 1101110 0100000 1101100 1100101 0100000 1100011 1101111 1110010 1100001 1101001 1101100 0100000 1100100 1101111 1110010 1110100

10010101100101010000011100111110101110100111100110100000111010011011111101101110001011001011100101
101010011011111110101111010001000001100101110111001000001101000110000111101011110100110010111101011110010



1101010 0100111 1100001 1101001 1101101 1100101  1101100 1100001  1101110 1110101 1101001 1110100

1001001 1101100 0100000 1110011 1100001 1101001 1100111 1101110 1100101 0100000 1110000 1100101 1110101 0101100
1000101 1110100 0100000 1110011 0100111 1010110 1101011 0100000 1110110 1100001 0100000 1110100 1101111 1110100

1010101 1101110 1101010 1101111 1110101 1110010 1110011 1100101 1101100 1100101 1110110 1100101
1001100 1100101 1110011 1101111 1101001 1110011 1100101 1100001 1110101 11110001100011 1101000 1100001 1101110 1110100 1100101 1101110 1110100

1001010 0100111 1100001 1101001 0100000 1110110 1110101 0100000 1101100 1100001 0100000 1101101 1100101 1110010
1010011 1110101 1110010 0100000 1101100 0100111 1001001 1101110 1110100 1100101 1110010 1101110 1100101 1110100

1010001 1110101 1101001 0100000 1110110 1100101 1110101 1110100 0100000 1100010 1101001 1100101 1101110 0100000 1100100 1101111 1101110 1101110 1100101 1110010 
0110001 0110000 1101000 0100000 1100100 1100100 0100000 1110011 1100101 1110011 0100000 1101010 1101111 1110101 1110010 1101110 1100101 1100101 1110011 0111111 


Le code ci-dessus converti en caractères (binaire vers ASCII) grâce à moulinette.py:

La voiture bouge
Le pied crisse
Le ceval rose
Perdant son ame
Qu'etait la vie
Le flux cosmique
La nuit est loin,
Le ciel est gris
Je suis tombee
Tout en hauteur
5lK5J 8.21JsMc1Js
j'aime la nuit
Il saigne peu,
Et s'Vk va tot
Un jour se leve
Les oiseaux chantent

23/09/2019: texte et code

Notes

* spécificité numérique
** virtuel, intangible
** source d'énergie, réseau (électrique ou autre)
** information codée, binaire

----> 0 1

compter en: 

base 10
0 1 2 3 4 5 6 7 8 9 10

base 4
0 1 2 3 10 11 12 13 20

base 2 (binaire)
0 1 10 11 100 101 110 111 1000


à chaque colonne une valeur:

16 8 4 2 1
1  0 1 1 1

comme en base 10:
  90  9
1 0   0

coder une couleur
128 64 32 16  8 4  2  1
1   1  1  1   1 1  1  1       0000 0000          0000 0010

= 256 valeurs possibles (en comptant le 0 comme une valeur) pour chaque canal de couleur (Rouge, Vert, Bleu)

1 canal est codé en 00000000 = 8 bits = 1 byte = 1 octet.

on peut donc coder une couleur avec 3 octets,
souvent représentés en base 16 (hexadécimal):

FF0000


Slides

Voir: slides 01: texte et code

1. INTERNATIONAL MORSE CODE, HAND SENDING - https://archive.org/details/gov.archives.arc.36813 Department of Defense. Department of the Army. Office of the Chief Signal Officer. (09/18/1947 - 02/28/1964)

  • Le code morse, inventé par Samuel F. B. Morse en 1832.
  • Directions pour tracer les lettres
  • Les confusions possibles si l'opérateur fait une erreur de rythme

2. TM 11-459 International Morse Code (Instruction) - 1959 - https://archive.org/details/Tm11-4591957/page/n3

  • Le télégraphe "a contribué plutôt à lier inextricablement la technologie et la place de l'humain" (K. Hayles - Lire et penser en milieux numériques p. 223)

3. Direct service guide for telegraphic cipher - 1939 - https://archive.org/details/directservicegui00sldu/page/20

  • Premier objectif: la compression (pour des raisons économiques)
  • 2e objectif: la discrétion
  • 3e objectif: le controle des erreurs

4. Bentley's second phrase code - 1929 - https://archive.org/details/bentleyssecondph00bent/page/778

  • Les codes ne sont plus liés au langage naturel

5. Idem

  • Ici, un "tableau de mutilation" qui permet de corriger un code mal transmis (qui contient une erreur d'une lettre)

6. Teleprinter n°7 - Creed & Company - 1930

  • Frederick G. Creed, inventeur du téléscripteur (vers 1910), ancien télégraphiste, canadien

7. Un exemple de téléscripteur - 1932, Londres

8. Code baudot - 1888

  • Un encodage des caractères sur 5 chiffres, 5 bits
  • Utilisé (dans des versions ultérieures) sur les premiers téléscripteurs
  • Nécessité de définir une vitesse de modulation, "baudrate" en anglais, qui définit le nombre de symboles envoyés en 1 seconde -> la question du début et de la fin!
  • Donald Murray adapte le code baudot en 1902 et attribue aux lettres les plus utilisées de l'alphabet les positions impliquant le moins de trous
  • En 1924, adaptation du code baudot-Murray par l'organisme International Telegraph Union en International Telegraph Alphabet No. 2 (ITA2)

9. ASCII - American Standard Code for Information Interchange - 1963 - pré 1971

  • sur 7 bits

Exercice : poésie binaire

Chaque étudiant.e écrit sur un pad commun au moins deux vers de 4 pieds en binaire en utilisant le tableau de conversion ASCII suivant: USASCII_code_chart.png

Fichier:Binarypoetry-2019-09-23 14.06.43 cut.mp4

Déroulement du cours

Le cours ne nécessite aucun prérequis si ce n'est une capacité d'attention pendant les séances. Cette attention implique qu'à certains moments, par exemple lors des moments de discussions ou de présentations, il sera demandé aux étudiant.e.s de fermer leur ordinateur, que l'usage des smartphones est interdit et que les étudiant.e.s doivent arriver à l'heure au cours (9h, le lundi matin).

Comme il s'agit d'un cours technique, les travaux se feront majoritairement en classe et il n'est pas absolument nécessaire de travailler en dehors du cours, à part pour documenter les travaux ou préparer leurs présentations (les cotations).

Le cours fonctionne en évaluation continue, ce qui signifie que chaque exercice réalisé en atelier aura une note attribuée. Pour réussir le cours, il faut essentiellement être présent.e.

À cette évaluation continue s'ajoute deux notes en décembre et en mai qui correspondent aux moments de cotations. Il est demandé pour ces cotations de présenter une sélection des travaux réalisés jusque là.

La difficulté technique, bien que présente, ne doit pas constituer une barrière pour assister au cours. Il ne sera pas demandé aux étudiant.e.s d'être performant.e.s mais plutôt de ne pas se braquer et d'accepter d'être inefficaces durant des périodes qui semblent parfois longues (voire trouver du plaisir dans ces périodes de recherches). L'entraide et le partage sont encouragés. Tout sera fait pour éviter des comportements de mise à distance du savoir entre celles et ceux "qui savent" et les "newbies".

Chaque étudiant.e a accès à ce wiki, qui servira durant toute l'année à documenter les travaux. La création des comptes pour le wiki se fait au début du deuxième cours (au moment de l'inscription au cours).