Outils pour utilisateurs

Outils du site


nsi:tds:flux_rss

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
nsi:tds:flux_rss [2023/05/26 06:36] – ↷ Liens modifiés en raison d'un déplacement. 40.77.167.146nsi:tds:flux_rss [2024/04/29 14:18] (Version actuelle) goupillwiki
Ligne 9: Ligne 9:
 Le [[https://fr.wikipedia.org/wiki/RSS|RSS]] (//Really Simple Syndication//) est un format de fichier dont le contenu est produit automatiquement pour tenir compte des mises à jours sur un site web (par exemple) Le [[https://fr.wikipedia.org/wiki/RSS|RSS]] (//Really Simple Syndication//) est un format de fichier dont le contenu est produit automatiquement pour tenir compte des mises à jours sur un site web (par exemple)
  
-> Syndication ou souscription : système qui consiste à vendre / fournir à plusieurs diffuseurs le droit de reproduire un contenu ou de diffuser un programme. Le diffuseur de contenu est appelé syndicate.+<WRAP tip>Syndication ou souscription : système qui consiste à vendre / fournir à plusieurs diffuseurs le droit de reproduire un contenu ou de diffuser un programme. Le diffuseur de contenu est appelé //syndicate//.</WRAP>
  
-Imaginons une situation : +**Imaginons une situation :** 
-  * A est un site produisant podcasts (par exemple ''%%www.franceculture.fr%%''). De nouveaux podcasts sont produits régulièrement.+  * A est un site produisant des podcasts (par exemple ''%%www.franceculture.fr%%''). De nouveaux podcasts sont produits régulièrement.
   * B est une application sur téléphone qui permet de s'abonner à divers podcasts.   * B est une application sur téléphone qui permet de s'abonner à divers podcasts.
  
Ligne 21: Ligne 21:
 Comme ce fichier RSS se remplit et se vide tout seul à mesure que les nouveaux podcasts sont créés puis deviennent périmés, on parle de flux. C'est donc un flux RSS. Comme ce fichier RSS se remplit et se vide tout seul à mesure que les nouveaux podcasts sont créés puis deviennent périmés, on parle de flux. C'est donc un flux RSS.
  
-//Bien sûr, j'ai parlé de podcasts, mais tout ce qui a été dit est valable pour n'importe quel type de contenu : des vidéos, des images, des articles, des news, des tweets...//+<WRAP tip> 
 +Bien sûr, j'ai parlé de podcasts, mais tout ce qui a été dit est valable pour n'importe quel type de contenu : des vidéos, des images, des articles, des news, des tweets, l'état du réseau RATP... 
 +</WRAP>
  
 ===== Format du flux RSS ===== ===== Format du flux RSS =====
Ligne 29: Ligne 31:
 Le fichier obtenu est au format ''%%*.xml%%''. C'est un simple fichier texte qui ressemble à : Le fichier obtenu est au format ''%%*.xml%%''. C'est un simple fichier texte qui ressemble à :
  
-<Code xml linenums>+<code xml linenums>
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
Ligne 57: Ligne 59:
   </channel>   </channel>
 </rss> </rss>
-</Code>+</code>
  
-> Il n'y a que deux articles dans ce flux. Je l'ai abrégé. Le flux original est beaucoup plus long.+<WRAP info>Il n'y a que deux articles dans ce flux. Je l'ai abrégé. Le flux original est beaucoup plus long.</WRAP>
  
-Le format XML est lourd et un peu pénible. C'est un format à **balises** comme HTML. Néanmoins il est très utilisé, c'est bien d'en avoir entendu parlé.+Le format XML est lourd et un peu pénible. C'est un format à **balises** comme HTML. Néanmoins il est très utilisé, c'est bien d'en avoir entendu parler.
  
 Quelques exemples ici dans ce fichier : Quelques exemples ici dans ce fichier :
Ligne 70: Ligne 72:
   * À l'intérieur de chaque article, d'autres balises donnent des informations. Pour le premier article par exemple, lignes 11 à 16, //title//, //description//, ...   * À l'intérieur de chaque article, d'autres balises donnent des informations. Pour le premier article par exemple, lignes 11 à 16, //title//, //description//, ...
  
-> Notez une différence avec HTML : en HTML, les balises ''%%<a>%%'', ''%%<div>%%'', etc. sont toutes des balises appartenant à la norme HTML. Il n'est pas prévu que l'on rajoute nos propres balises. En XML c'est différent. XML décrit seulement l'organisation des balises mais nous sommes libres de créer des balises avec les noms que l'on veut, du moment que l'on respecte la forme ''%%<balise>...</balise>%%'' ou éventuellement ''%%<balise options />%%''+<WRAP tip> 
 +Notez une différence avec HTML : en HTML, les balises ''%%<a>%%'', ''%%<div>%%'', etc. sont toutes des balises appartenant à la norme HTML. Il n'est pas prévu que l'on rajoute nos propres balises. En XML c'est différent. XML décrit seulement l'organisation des balises mais nous sommes libres de créer des balises avec les noms que l'on veut, du moment que l'on respecte la forme ''%%<balise>...</balise>%%'' ou éventuellement ''%%<balise options />%%''
 +</WRAP>
 ==== XML avec Python ==== ==== XML avec Python ====
  
Ligne 78: Ligne 81:
 En python on pourra utiliser [[https://www.fil.univ-lille1.fr/~marvie/python/chapitre4.html#minidom-il-fait-le-maximum|xml.dom.minidom]] : En python on pourra utiliser [[https://www.fil.univ-lille1.fr/~marvie/python/chapitre4.html#minidom-il-fait-le-maximum|xml.dom.minidom]] :
  
-<Code python>+<code python>
 import xml.dom.minidom as xml import xml.dom.minidom as xml
 # si le xml est dans un fichier, par ex flux_rss.xml : # si le xml est dans un fichier, par ex flux_rss.xml :
Ligne 85: Ligne 88:
 # si le xml est dans une chaîne de caractère, par ex reponseXML # si le xml est dans une chaîne de caractère, par ex reponseXML
 xml_doc = xml.parseString(reponseXML) xml_doc = xml.parseString(reponseXML)
-</Code>+</code>
  
 Le document est construit sous forme d'un arbre (//pensez à un arbre généalogique//) : une balise enferme d'autres balises qui sont ses enfants. Une des balise (dans l'exemple la balise ''%%<rss>%%'' contient l'ensemble. C'est la **racine**. Le document est construit sous forme d'un arbre (//pensez à un arbre généalogique//) : une balise enferme d'autres balises qui sont ses enfants. Une des balise (dans l'exemple la balise ''%%<rss>%%'' contient l'ensemble. C'est la **racine**.
  
-<Code python>+<code python>
 root = xml_doc.documentElement # racine root = xml_doc.documentElement # racine
-</Code>+</code>
  
 On peut ensuite parcourir les enfants, les enfants des enfants : On peut ensuite parcourir les enfants, les enfants des enfants :
  
-<Code python>+<code python> 
 +# root.getElementByTagName('item') renvoie la liste des noeuds <item> sous root
 for article in root.getElementsByTagName('item'): for article in root.getElementsByTagName('item'):
-    # article correspond à un noeud <item> trouvez sous la racine +    # article correspond à un des noeuds <item> 
-    child0 = article.childNodes[0] # premier noeud enfant de article +    titlenode = article.childNodes[0] # premier noeud enfant de article 
-    print(child0.data ) # contenu du noeud +    # dans le flux, l'enfant [0] est toujours un noeud <title> 
-</Code>+    # donc titlenode est un noeud <title> 
 +    textnode = titlenode.childNodes[0] 
 +    # titlenode a un unique enfant, c'est un noeud de texte 
 +    # textnode est donc le noeud contenant le texte du noeud <item> titlenode 
 +    print(textNode.data) # par exemple, on affiche le contenu de textnode, c'est à dire le titre 
 +</code>
  
 ===== Implémentation Python ===== ===== Implémentation Python =====
Ligne 109: Ligne 118:
   - affichage des titres (//à faire//)   - affichage des titres (//à faire//)
  
-> **Remarque :** La plupart des sites sont aujourd'hui en https, c'est à dire chiffrés. Cela occasionne quelques complications. J'ai commenté autant que possible pour que vous compreniez le principe général. Dans tous les cas, gardez à l'esprit que, en fonction des évolutions des technologies, on est obligé de s'adapter. Par exemple, ici, j'ai découvert la bibliothèque python ssl à l'occasion de cet exercice. On a donc besoin de savoir lire des documentations sur internet pour prendre en main ces outils.+<WRAP tip>**Remarque :** La plupart des sites sont aujourd'hui en https, c'est à dire chiffrés. Cela occasionne quelques complications. J'ai commenté autant que possible pour que vous compreniez le principe général. Dans tous les cas, gardez à l'esprit que, en fonction des évolutions des technologies, on est obligé de s'adapter. Par exemple, ici, j'ai découvert la bibliothèque python ssl à l'occasion de cet exercice. On a donc besoin de savoir lire des documentations sur internet pour prendre en main ces outils.</WRAP>
  
- +<code python linenums> 
-<Code python linenums>+# rss.py
 # lecture flux RSS # lecture flux RSS
  
 import socket       # pour création socket TCP-IP import socket       # pour création socket TCP-IP
 import ssl          # gestion chiffrement pages https import ssl          # gestion chiffrement pages https
- +import urllib.request as req
-# le flux qui nous sert d'exemple est un flux d'actualité sur wwww.francetvinfo.fr +
-# on donne l'adresse du serveur (domaine) +
-hostname = 'www.francetvinfo.fr' +
- +
-# adresse du flux lui-même +
-address = 'https://www.francetvinfo.fr/titres.rss' +
- +
-# création d'un contexte sécurisé avec ssl +
-context = ssl.SSLContext() +
- +
-HTTP_VERSION = 1.0 +
-CRLF = "\r\n\r\n" +
- +
-# Dans certains cas on utilise une ressource. Il faut demander au système d'exploitation +
-# de nous donner accès à cette ressource puis il faut lui dire quand on libère cette ressource. +
-# ex : ouverture / fermeture de fichier ; ouverture / fermeture de connexion +
-# avec le mot clé with, on crée un bloc qui réserve la ressource +
-# puis la libère dès qu'on sort du bloc. +
- +
-# 443 est le port habituel pour https +
-with socket.create_connection((hostname, 443)) as sock: +
-    # sock est "emballé" dans le contexte sécurisé (donnée cryptée) avec ssl +
-    with context.wrap_socket(sock, server_hostname=hostname) as ssock: +
-        # lancement la requête GET en précisant l'adresse +
-        ssock.send("GET {} HTTP/{} {}".format(address, HTTP_VERSION, CRLF).encode()) +
-        # la taille de la réponse est inconnue. +
-        # on réceptionne par morceaux de 1024 octets. +
-        reponseXML = "" # au début la réponse est vide. +
- +
-        while True: +
-            block = ssock.recv(1024) +
-            if not block: +
-                # block est vide, il n'y a plus rien à récupérer +
-                # sortie de la boucle +
-                break +
- +
-            # À l'usage je n'ai pas pu clairement définir l'encodage utilisé... +
-            # le bloc qui suit consiste à tenter (try) un décodage en utf-8 +
-            # et si cette tentative provoque une erreur, +
-            # recommencer mais avec un décodage en iso +
-            try: +
-                reponseXML += block.decode("utf-8"+
-            except: +
-                reponseXML += block.decode("ISO-8859-2"+
- +
-# arrivé à ce point, reponseXML contient le texte de réponse. +
-# chargement de la bibliothèque xml+
 import xml.dom.minidom as xml import xml.dom.minidom as xml
  
-# votre travail +def get_xml(url): 
-def getTitles(texteXml):+    """ 
 +    url: adresse du flux rss 
 +    renvoie le contenu du fichier xml 
 +    """ 
 +    context = ssl.SSLContext() 
 +    with req.urlopen(url, context=context) as reponse: 
 +        return reponse.read().decode('utf8'
 +     
 +def get_titles(texte_xml):
     '''     '''
-    texteXml : le texte XML dans lequel chercher+    texte_xml : le texte XML dans lequel chercher
     retourne l'ensemble des titres (contenus dans <title>...</title>)     retourne l'ensemble des titres (contenus dans <title>...</title>)
     sous forme d'une liste.     sous forme d'une liste.
Ligne 176: Ligne 146:
     # à vous !     # à vous !
     pass     pass
- +</code>
-# Et pour finir, utilisez la fonction getTitles pour obtenir les titres +
-# et affichez-les. +
-</Code>+
  
 <WRAP important>En ligne 14 j'ai changé l'ancien ''context = ssl.create_default_context()'' qui ne fonctionnait plus pour ''ssl.SSLContext()''. Ce n'est pas idéal car ce choix fait qu'on ne vérifie pas le certificat ssl du site. Cela nous évite les erreurs mais est potentiellement dangereux (les certificats sont là pour la sécurité). Toutefois, dans le cadre de ce TP on échange aucune donnée sensible et on ne risque rien.</WRAP> <WRAP important>En ligne 14 j'ai changé l'ancien ''context = ssl.create_default_context()'' qui ne fonctionnait plus pour ''ssl.SSLContext()''. Ce n'est pas idéal car ce choix fait qu'on ne vérifie pas le certificat ssl du site. Cela nous évite les erreurs mais est potentiellement dangereux (les certificats sont là pour la sécurité). Toutefois, dans le cadre de ce TP on échange aucune donnée sensible et on ne risque rien.</WRAP>
- 
-<WRAP tip>Tout le bloc des lignes 1 à 49 permet de comprendre le principe de l'échange. On peut passer par des modules qui font le tout de façon plus courtes. 
  
 <code python linenums> <code python linenums>
-import ssl +# main.py 
-import urllib.request as req + 
-url = "https://www.francetvinfo.fr/titres.rss" +from  rss import get_xml, get_titles 
-context ssl.SSLContext()  # supprime la vérification du ssl + 
-reponseXML req.urlopen(url, context=context).read()+# adresse du flux lui-même 
 +url = 'https://www.francetvinfo.fr/titres.rss' 
 +  
 +xml get_xml(url
 +titles get_titles(xml) 
 + 
 +# affiche les 3 premiers titres 
 +print(titles[:3])
 </code> </code>
-</WRAP> 
nsi/tds/flux_rss.1685075783.txt.gz · Dernière modification : de 40.77.167.146