Enregistrer ou imprimer toutes les pages d'un sujet

2 participants

Voir le sujet précédent Voir le sujet suivant Aller en bas

Résolu Enregistrer ou imprimer toutes les pages d'un sujet

Message par MlleAlys Mar 23 Aoû 2022 - 17:51

Détails techniques


Version du forum : phpBB2
Poste occupé : Fondateur
Navigateur(s) concerné(s) : Google Chrome
Personnes concernées par le problème : Tous les utilisateurs
Lien du forum :

Description du problème

Bonjour,

Je cherche à récupérer le contenu de différents sujets... dont certains font plusieurs dizaines de pages !
Autant vous dire que après avoir commencé avec des copier/coller (pour récupérer seulement le contenu des messages), puis être passée sur une impression directe de chaque page une par une, pour ensuite fusionner mes documents par sujet... ma motivation en a pris assez vite un coup ! Laughing

Existe-t-il une astuce ou un code permettant d'enregistrer ou d'imprimer toutes les pages d'un sujet d'un seul coup ?
(sinon, je sens que je vais le proposer en suggestion, même si je doute de son succès Razz )

Merci ! drunken
MlleAlys

MlleAlys
Membre actif

Messages : 5967
Inscrit(e) le : 12/09/2012

MlleAlys a été remercié(e) par l'auteur de ce sujet.
  • 0

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par Toryudo Mer 24 Aoû 2022 - 13:51

Bonjour !
Je pense pouvoir bricoler quelque chose en passant par un HTML personnalisé avec un champ à remplir (un lien vers le sujet en question). Un script irait alors automatiquement regarder le sujet, recopierait les messages, et parcourrait toutes les pages dudit sujet pour afficher toutes les réponses les unes à la suite des autres sur une seule et même page.
Ça permettrait de pouvoir sauvegarder la page ainsi générée, ou même l'imprimer.

Est-ce que ça conviendrait ?
Est-ce qu'il y aurait des choses particulières à récupérer ou à ne pas récupérer ?
Est-ce qu'on garde les profils, les messages, la mise en forme, les signatures, tout ?
Toryudo

Toryudo
Aidactif
Aidactif

Masculin
Messages : 1564
Inscrit(e) le : 31/03/2020

https://deus-academia.forumactif.com/
Toryudo a été remercié(e) par l'auteur de ce sujet.

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par MlleAlys Mer 24 Aoû 2022 - 15:46

ooooooh merci Toryudo !
J'essayais aussi de faire une sorte de formulaire sur une page html de mon forum test !
Et... bon... clairement pour l'instant sans succès, le javascript c'est toujours pas mon truc, je galère, j'ai l'impression d'écrire des trucs hyper moches et peu efficaces, je ne sais pas me servir de la console et je me retrouve à ajouter des alert() à chaque nouvelle ligne pour voir si ça fonctionne ! Laughing  
Ton aide sera la bienvenue !
Je souhaite pouvoir récupérer le titre du sujet, le sondage s'il y en a un, le contenu des messages avec le pseudo du posteur ;
Si possible sans signature, et pour les champs du profil à vrai dire j'ai hésité mais j'ai finalement choisi non !

Attention, réflexions d'une pas douée en javascript qui a essayé quand même :

    Première étape de ma réflexion : réussir à charger les éléments de la première page donnée :
  1. souhaitant possiblement l'utiliser sur plusieurs forums, je me suis dit que soit il fallait que le code soit capable de reconnaitre ces éléments sur la page de lui même, quelque soit les possibles personnalisations du forum.... soit, étant incapable de faire cette première possibilité, j'allais lui donner moi même les sélecteurs des éléments en question ! xD Donc j'ai fait un formulaire avec différents champs pour le lien, le sélecteur de la pagination, celui du titre, des messages, et des pseudos (pré-remplis avec les sélecteurs de mon forum test).

  2. je souhaitais au départ faire sur une page html vierge, mais sans jquery et ne sachant pas comment intégrer cette bibliothèque, j'ai finalement opté par défaut pour une page html avec le haut et le bas de mon forum test.  Laughing

  3. j'ai utilisé la fonction load(), mais je ne savais pas s'il valait mieux charger chaque élément dans le bloc voulu, ou bien charger en une seule fois toute la page puis redistribué les éléments dans les blocs voulus... J'ai opté pour la première version, mais je ne sais pas tellement si ça ralenti beaucoup ou pas.

  4. quand il s'agit de charger un seul élément dans une div cible tout va bien (genre le titre), mais pour ce qui est des messages + pseudos, pour l'instant il me met ça en vrac, dans l'ordre dans lequel il les a trouvés sur la page (donc si les profils sont à droite des messages, il affiche le pseudo après le message). Je ne sais pas s'il y a un moyen de "trier" chaque élément pour les placer et les encadrer de balises ; j'imagine que oui, mais dans ce cas j'imagine qu'il faudrait plutôt passer par un chargement complet de la page avant de pouvoir redistribuer les éléments obtenus ?
    En vrai, j'aimerais pouvoir appliquer une mise en forme extrêmement simple (mais pour l'instant ça dépend justement des sélecteurs du forum du sujet), et avoir le pseudo avant le message (ou à côté), mais ça reste de la mise en forme et du bonus pour moi xD

  5. je me suis demandé si c'était possible de faire un message d'erreur quand il n'y a pas d'accès au sujet (manque de permission ou besoin de se connecter) et... je me suis dit que ce serai également du bonus à la fin ! xP

    Deuxième étape de ma réflexion : charger les pages suivantes :

  6. J'ai bien réussi je pense à récupérer la pagination, à récupérer à partir de celle-ci le nombre de pages.

  7. j'ai utilisé split() pour récupérer seulement le début du lien, jusqu'au numéro du sujet
    j'ai ajouté manuellement dans ma boucle pour chaque page le "p" avec le nombre de messages par page (que j'ai également mis dans le formulaire, parce que avec les contenus sponsorisés etc, je ne savais pas comment le retrouver automatiquement).
    Jusque là tout allait bien, j'avais bien les différents liens de toutes les pages du sujet.

  8. Je me suis demandé si je devais charger toutes les pages dans une variable et les afficher seulement à la fin, ou bien les afficher au fur et à mesure. en parallèle, je ne savais pas comment ajouter mon contenu à la suite de la première page plutôt que de remplacer tout le contenu. J'ai croisé la fonction get(), j'ai essayé, ça n'a rien donné... Du coup j'ai contourné le problème en créant un nouveau bloc pour chaque nouvelle page, je me suis dit que c'était pas plus mal pour une possible mise en forme future  Razz

  9. j'ai tenté de charger donc toujours avec load dans chacun de ces blocs. J'ai bien les blocs. Je peux écrire dedans avec html(). Mais le load ne fonctionne pas.
    Je me suis demandée si ça pouvait venir du fait que le lien était "incomplet", dans le titre du sujet.
    Je me suis dit qu'à cela ne tienne, je récupère mon lien split, j'ajoute mon petit bout, et je reforme mon lien complet à nouveau à partir de là !
    Pour éviter que les numéros de pages ne s'accumulent plutôt que de se remplacer, j'ai utilisé deux variables, une pour garder le lien de départ de côté, l'autre pour ajouter à chaque itération de ma boucle le numéro de page.

    ET LA, LA !!!!! Je ne comprends pas !! ça ne fonctionne pas, ma première variable est modifiée en même temps que la deuxième et ça me parait tellement illogique que je bloque complètement ! j'ai essayé de tourner mon code de toutes les façons imaginables, rentrer ou sortir les variables de la boucle, réinitialiser à chaque fois, générer le lien à partir de la première, de la deuxième, j'ai mis des alert partout pour tenter de comprendre, rien n'y fait, alors que c'est précisément ce que je veux éviter, les numéros de pages s'accumulent au lieu d'être remplacés !!
    Je ne comprends pas !!  Evil or Very Mad  




BREF,
tout ça pour dire que je ne suis pas sûre que mon code soit vraiment efficace, j'ai conscience qu'il faudra sûrement de toute façon tout refaire, mais si on pouvait au moins m'éclairer sur ce dernier point qui reste pour moi un mystère, ça serait super.... Embarassed


Ma page html actuelle :
https://mllealys2.forumactif.org/h16-chargement-sujet-entier

mon fabuleux code de cette page  Laughing :
Code:
<script>
  function charger() {
  
  //chargement des éléments
  
  //lien
  var lien = document.getElementById("liensujet").value;
  
  
  //charger titre
  var selecttitre = document.getElementById("selecttitre").value;
  $("#sujettitre").load( lien + " " + selecttitre );
  
  //sondage
  $("#sondage").load( lien + " table.poll-result" );
  
  //pseudos
  var selectpseudo = document.getElementById("selectpseudo").value;
  if(selectpseudo != ""){ selectpseudo = " " + selectpseudo };
  
  //messages
  var selectmsg = document.getElementById("selectmsg").value;
  if(selectmsg != ""){ selectmsg = ", " + selectmsg };
  
  //charger le rp
  $("#sujetcontenu").load( lien + selectpseudo + selectmsg );
  

  //charger pagination
  var selectpag = document.getElementById("selectpag").value;
  $("#pagination").load( lien + " " + selectpag , function(){
  
      //tester pagination
      var pages = $('#pagination').text();
      if ( pages == "") { alert("Pas d\'autres pages trouvées."); $('#pagination').text("Pas d\'autres pages trouvées.");}
      else {  
  
  // s'il y a d'autres pages
  $('#pagination img').parent().remove();
  var nbpages = parseInt($('#pagination a:last-child').text());
  if( confirm( nbpages + " autres pages ont été trouvées ! Les charger ?") !=true){return;};
  
  // chargement des pages
  var increment = parseInt( document.getElementById("increment").value );
  lien = lien.split('-');
  
  for( var i=1; i < nbpages ; i++ ) {
  var page = lien ;
  page[0] = page[0] + "p" + increment * i ;
  
  page = page.join('-');
alert ( page );


var num = i + 1 ;
var blocsuite = '<div id="p' + num + '"></div>';
$("#sujet").append( blocsuite );

$("#sujet>div:last-child").html( "load page " + num );

delete page ;

  }; //fin du for
  
  }; // fin du else
  }); // fin du load pagination
  
  
  
  
  }; // fin de la fonction du bouton
  
</script>

<form>
  <input type="url" placeholder="lien du sujet" value="" id="liensujet" name="liensujet" />
  <input type="text" placeholder="sélecteur pagination" value="td.pagination span.gensmall" id="selectpag" />
  <input type="text" placeholder="nombre de posts par page" value="5" id="increment" />
  <input type="text" placeholder="sélecteur titre du rp" value=".catHead h1" id="selecttitre" />
  <input type="text" placeholder="sélecteur pseudo" value=".post .name" id="selectpseudo" />
  <input type="text" placeholder="sélecteur message" value="tr.post .postbody" id="selectmsg" />
  <button type="button" onclick="charger();">Charger le sujet !</button>
</form>


<div id="pagination"></div>
<div id="sujet">
  <div id="sujettitre"></div>
<div id="sondage"></div>
  <div id="sujetcontenu"></div>
</div>


<style>
  form {
  border: 2px solid black;
  padding: 10px;
  text-align: center;
  font-size: 14px;
  font-weight: bold;
  margin: 10px;
}
  #page-body form input {
  display: block;
  margin: 10px auto;
  width:250px;
}
#pagination {
  text-align: center;
  border: 1px solid black;
  padding: 10px;
  margin: 10px;
}
  #sujet {
  border: 1px solid black;
  padding: 10px;
  margin: 10px;
  overflow: auto;
  max-height: 500px;
}
  div#sujettitre, div#sujettitre * {
  text-align: center;
  font-size: 18px;
  margin-bottom: 25px;
  text-decoration: underline;
}
</style>

J'ai testé sur différents sujets de mon forum test et d'autres forums à gauche à droite, dont par exemple ceux-ci, qui ne sont pas trop personnalisés :




EDIT :
- J'avais également pensé à la possibilité d'avoir un bouton pour pouvoir, à la fin du chargement, copier tout le contenu du sujet d'un coup, ou au moins tout sélectionner ; mais pareil c'est du bonus auquel je n'ai même pas encore réfléchi ! xP
MlleAlys

MlleAlys
Membre actif

Messages : 5967
Inscrit(e) le : 12/09/2012

MlleAlys a été remercié(e) par l'auteur de ce sujet.
  • 0

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par Toryudo Mer 24 Aoû 2022 - 20:06

Le code est plutôt pas mal, pas de gros problème (même si en effet, j'ai eu envie de tout réécrire Razz).
Le seul défaut que je vois, c'est que chaque load redemande à charger une page. La récupération du titre charge une page, la récupération du sondage charge une page, la récupération des sujets/contenus charge une page... tout ça alors qu'au final, en chargeant la page une fois et en piochant dedans, on s'épargne quelques chargements.

1) Alors, j'ai gardé la logique des inputs pour rentrer les infos qu'on veut, j'en ai retiré une (le nombre de messages par pages) et j'en ai ajouté une (le code d'un message dans lequel on pourra trouver le pseudo et le contenu).

2) Pour pouvoir utiliser le jquery, il suffirait de rajouter la ligne suivante avant les scripts qui utilisent du jquery :
Code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
Mais soit, faisons-le sans jquery, parce que c'est possible.

3) A la place des load, on va utiliser un fetch. Ça permet de récupérer le texte d'une page, qu'on convertit ensuite en Object HTML.
Code:
      // Chargement de la première page
      const response = await fetch(lien);
      const html = await response.text();

      // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');
En gros, à partir de là, on peut utiliser la variable doc comme on utilise document (par exemple, doc.getElementById(), ce serait une récupération de balise id sur le lien chargé)

4) Puisqu'on passe maintenant par des posts plutôt que des pseudos ou des messages, on boucle sur les posts, et on récupère les pseudos puis les messages. Comme ça, on aura toujours le bon ordre :
Code:
      const posts = doc.querySelectorAll(selectpost);
      posts.forEach(function(post) {
         const pseudo = post.querySelector(selectpseudo);
         const contenu = post.querySelector(selectmsg);

         document.getElementById('sujetcontenu').appendChild(pseudo);
         document.getElementById('sujetcontenu').appendChild(contenu);
      });

5) A voir, il faudrait rajouter un peu de code, vérifier qu'est-ce qui s'affiche dans toutes les versions. Effectivement, pour l'instant, je pense que le script va planter.
Ça pourra être une amélioration, c'est pas grave.

6) Je fais ça un peu plus simplement, en regardant l'avant dernier lien numéroté dans la zone pagination. Avant dernier, parce que le dernier, c'est la flèche pour aller à la page suivante, mais moi, je cherche à savoir le nombre de pages :
Code:
      // Récupération du nombre de pages du sujet
      let nbPages = 1;
      const pagination = doc.querySelector(selectpag + ' a:nth-last-child(2)');
      if (pagination){
         nbPages = pagination.innerText;
      }
Maintenant, je vais pouvoir boucler nbPages fois pour récupérer toutes les pages.

7) Pareil, j'ai repris le code. J'utilise juste posts.length pour avoir le nombre de posts par page, c'est pour ça que je n'ai pas besoin d'input avec cette information.

8 et 9) J'ai décidé de charger les pages les unes à la suite des autres, et de reprendre le principe de la récupération des posts, des pseudos et des messages. Je suis obligé d'écrire le fetch un peu différemment pour que le JavaScript ne fasse pas les chargements de toutes les pages en parallèle (ce qu'il ferait si on ne lui disait rien), avec un await. On part peut-être dans du "un peu plus compliqué à comprendre et à refaire", mais ce que ça veut dire, c'est qu'il va attendre la fin du chargement de la page 2 avant de commencer celui de la page 3, et ainsi de suite.
Code:
         // Chargement d'une nouvelle page
         await fetch(lienPage).then(function (response) {
            return response.text();

         }).then(function (htmlPage) {

            // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
            const parserPage = new DOMParser();
            const docPage = parserPage.parseFromString(htmlPage, 'text/html');

            // Récupération des pseudos et messages
            docPage.querySelectorAll(selectpost).forEach(function(postPage) {
               const pseudoPage = postPage.querySelector(selectpseudo);
               const contenuPage = postPage.querySelector(selectmsg);

               document.getElementById('sujetcontenu').appendChild(pseudoPage);
               document.getElementById('sujetcontenu').appendChild(contenuPage);
            });
         });

Conclusion :
Et voilà, tout charge en même temps et tout s'affiche dans le bon ordre, si je n'ai pas oublié des cas ni fait trop de bêtises...
Désolé par contre, pour le point mystère, je n'arrive pas trop à me rendre compte...

Voilà le code final, une page HTML à éditer en "Modification en mode avancé" pour plus de propreté !
Code:
<!DOCTYPE html>
<html lang="fr" xml:lang="fr">
<head>
   <meta charset="UTF-8" />
   <title>Mon récupérateur de texte</title>
   <style>
      form {
         border: 2px solid black;
         padding: 10px;
         text-align: center;
         font-size: 14px;
         font-weight: bold;
         margin: 10px;
      }
      #page-body form input {
         display: block;
         margin: 10px auto;
         width:250px;
      }
      #pagination {
         text-align: center;
         border: 1px solid black;
         padding: 10px;
         margin: 10px;
      }
      #sujet {
         border: 1px solid black;
         padding: 10px;
         margin: 10px;
         overflow: auto;
         max-height: 500px;
      }
      div#sujettitre, div#sujettitre * {
         text-align: center;
         font-size: 18px;
         margin-bottom: 25px;
         text-decoration: underline;
      }
      .postbody {
         margin-bottom: 10px;
      }
   </style>
</head>
<body>

<form>
   <input type="url" placeholder="lien du sujet" value="" id="liensujet" name="liensujet" />
   <input type="text" placeholder="sélecteur pagination" value="td.pagination span.gensmall" id="selectpag" />
   <input type="text" placeholder="sélecteur titre du rp" value=".catHead h1" id="selecttitre" />
   <input type="text" placeholder="sélecteur post" value="tr.post" id="selectpost" />
   <input type="text" placeholder="sélecteur pseudo" value=".name" id="selectpseudo" />
   <input type="text" placeholder="sélecteur message" value=".postbody" id="selectmsg" />
   <button type="button" onclick="charger();">Charger le sujet !</button>
</form>

<div id="pagination"></div>
<div id="sujet">
   <div id="sujettitre"></div>
   <div id="sondage"></div>
   <div id="sujetcontenu"></div>
</div>

<script>

   /**
    * Chargement de la première page
    */
   async function charger() {

      // Lien
      const lien = document.getElementById("liensujet").value;
      const selectpag = document.getElementById("selectpag").value;
      const selecttitre = document.getElementById("selecttitre").value;
      const selectpost = document.getElementById("selectpost").value;
      const selectpseudo = document.getElementById("selectpseudo").value;
      const selectmsg = document.getElementById("selectmsg").value;

      // Chargement de la première page
      const response = await fetch(lien);
      const html = await response.text();

      // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');

      // Récupération du titre du sujet
      document.getElementById('sujettitre').replaceChildren();
      const titre = doc.querySelector(selecttitre);
      document.getElementById('sujettitre').appendChild(titre);

      // Récupération du sondage du sujet
      document.getElementById('sondage').replaceChildren();
      const sondage = doc.querySelector('table.poll-result');
      if (sondage){
         document.getElementById('sondage').appendChild(sondage);
      }

      // Récupération des pseudos et messages
      document.getElementById('sujetcontenu').replaceChildren();
      const posts = doc.querySelectorAll(selectpost);
      posts.forEach(function(post) {
         console.log(post);
         const pseudo = post.querySelector(selectpseudo);
         const contenu = post.querySelector(selectmsg);

         document.getElementById('sujetcontenu').appendChild(pseudo);
         document.getElementById('sujetcontenu').appendChild(contenu);
      });

      // Récupération du nombre de pages du sujet
      let nbPages = 1;
      const pagination = doc.querySelector(selectpag + ' a:nth-last-child(2)');
      if (pagination){
         nbPages = pagination.innerText;
      }

      // Récupération du contenu des autres pages
      for (let i = 1; i < nbPages; i++){

         let lienPage = lien.split('-');
         lienPage[0] = lienPage[0] + "p" + (posts.length * i);
         lienPage = lienPage.join('-');

         // Chargement d'une nouvelle page
         await fetch(lienPage).then(function (response) {
            return response.text();

         }).then(function (htmlPage) {

            // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
            const parserPage = new DOMParser();
            const docPage = parserPage.parseFromString(htmlPage, 'text/html');

            // Récupération des pseudos et messages
            docPage.querySelectorAll(selectpost).forEach(function(postPage) {
               const pseudoPage = postPage.querySelector(selectpseudo);
               const contenuPage = postPage.querySelector(selectmsg);

               document.getElementById('sujetcontenu').appendChild(pseudoPage);
               document.getElementById('sujetcontenu').appendChild(contenuPage);
            });
         });
      }
   }
</script>
</body>
</html>
Toryudo

Toryudo
Aidactif
Aidactif

Masculin
Messages : 1564
Inscrit(e) le : 31/03/2020

https://deus-academia.forumactif.com/
Toryudo a été remercié(e) par l'auteur de ce sujet.

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par MlleAlys Mer 24 Aoû 2022 - 21:58

(même si en effet, j'ai eu envie de tout réécrire Razz)
Déjà avec de html et du css ça me fait cet effet là, alors avec du javascript j'imagine encore plus ! Razz

Pour pouvoir utiliser le jquery, il suffirait de rajouter la ligne suivante avant les scripts qui utilisent du jquery :
Oh la la faut que je la garde quelque part celle là, merci !

J'utilise juste posts.length pour avoir le nombre de posts par page
J'avais également pensé à ça, mais les pubs qui sont affichées parfois en fin de page comme un message (avec même un .postbody), et qui du coup sont aussi importées avec mon code d'essai, m'ont fait peur... C'est pour ça que j'ai contourné le problème avec le input : Pourquoi ici n'est-ce pas un souci ? Ne devraient-ils pas être comptabilisés également, et fausser le nombre de messages sur la page ?
Enregistrer ou imprimer toutes les pages d'un sujet Image76

pour que le JavaScript ne fasse pas les chargements de toutes les pages en parallèle (ce qu'il ferait si on ne lui disait rien), avec un await
Oh, ça c'est une difficulté que je rencontre souvent avec le javascript !! Il va falloir que je creuse ça ! **

"un peu plus compliqué à comprendre et à refaire"
Alors, déjà tout le reste, je comprends les grandes lignes, mais dans les détails je ne comprends pas tout, et je serais bien incapable de refaire ! Razz Je viens de découvrir (ou redécouvrir pour certaines ?) des choses comme "const", "let", "querySelectorAll".... J'ai du boulot !  Laughing

à éditer en "Modification en mode avancé"
(Ah bon, parce qu'il existe un autre mode ? Laughing )


Merci beaucoup pour ton aide ! ça semble bien fonctionner, et je crois que jamais je n'aurais réussi à obtenir un résultat aussi efficace par moi même ! I love you I love you

- si je veux, pour des envies de mise en forme, insérer chaque pseudo et messages dans des balises spécifiques ou leur appliquer une class chacun (et du coup avoir un css qui ne dépendrait pas de la personnalisation du forum d'origine du sujet), est-ce faisable facilement ? Où est-ce que je peux l'insérer dans le code ? J'ai essayé à quelques endroits mais chaque fois ça a tout cassé Razz
EDIT : ou alors modifier le sélecteur du css en fonction de celui indiqué dans les input ?  scratch

- sur mon forum test, aucun problème, mais lorsque j'essaye avec la deuxième adresse proposée dans mon message précédent, il y a un souci d'affichage des caractères avec accents ? scratch
J'ai prérempli les input avec le sujet en question ici : https://mllealys2.forumactif.org/h17-charger-contenu-sujet-entier
Enregistrer ou imprimer toutes les pages d'un sujet Image77


Merci encore pour ton aide ! sunny



EDIT :

J'ai une nouvelle question ! Embarassed
Quand on fait "imprimer" la page, en tout cas avec chrome, on peut avec en option des en-tête et le pied de page : Il contiennent sur ce navigateur la date, l'adresse du site, le titre de la page web, le numéro de page de l'impression...
Sont-ils définis par le navigateur ? Peut-on les définir dans la page elle même ?
MlleAlys

MlleAlys
Membre actif

Messages : 5967
Inscrit(e) le : 12/09/2012

MlleAlys a été remercié(e) par l'auteur de ce sujet.
  • 0

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par Toryudo Jeu 25 Aoû 2022 - 8:01

Effectivement, je n'avais pas pensé au contenu sponsorisé...
Si on regarde, c'est toujours le .post--0, donc pour ne pas le sélectionner, on peut juste modifier le sélecteur post :
Code:
<input type="text" placeholder="sélecteur post" value="tr.post:not(.post--0)" id="selectpost" />

Pour tout ce qui est pseudo et message, on peut ajouter des nouvelles class si on veut, oui, on procède comme ceci en JavaScript natif, et on le place comme ceci :
Code:
let pseudo = post.querySelector(selectpseudo);
let contenu = post.querySelector(selectmsg);

pseudo.classList.add('maNouvelleClassPseudo');
contenu.classList.add('maNouvelleClassContenu');

document.getElementById('sujetcontenu').appendChild(pseudo);
document.getElementById('sujetcontenu').appendChild(contenu);

Alors, pour les caractères spéciaux, ça vient du fait que notre page est encodée en utf-8 alors que la page à charger est encodée en windows-1252. Là comme ça, je ne sais pas pourquoi, sachant que je teste avec un forum en phpbb2 et qu'il est bien en utf-8 (sûrement une question de date de création du forum, tout est en utf-8 partout maintenant). Du coup, il va falloir modifier des choses et en rajouter d'autres :
- on rajoute un input avec l'encodage de la page à charger (c'est un peu pénible, parce qu'il faut chercher l'encodage de la page en question, ce sera windows-1252 pour l'exemple de ce lien)
- on modifie le code des fetch pour rajouter un Decoder, qui va s'occuper de convertir le format indiqué vers utf-8

Code:
      // Chargement de la première page
      const response = await fetch(lien);
      const buffer = await response.arrayBuffer();
      
      // On convertit le format vers utf-8
      const decoder = new TextDecoder(selectencodage);
      const html = decoder.decode(buffer);

      // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');

J'ai intercalé un const buffer = await response.arrayBuffer(); et les lignes du decoder.
Ça fait pas mal de modifications, donc voilà ce que donne le script final :

Code:
<!DOCTYPE html>
<html lang="fr" xml:lang="fr">
<head>
   <meta charset="UTF-8" />
   <title>Mon récupérateur de texte</title>
   <style>
      form {
         border: 2px solid black;
         padding: 10px;
         text-align: center;
         font-size: 14px;
         font-weight: bold;
         margin: 10px;
      }
      #page-body form input {
         display: block;
         margin: 10px auto;
         width:250px;
      }
      #pagination {
         text-align: center;
         border: 1px solid black;
         padding: 10px;
         margin: 10px;
      }
      #sujet {
         border: 1px solid black;
         padding: 10px;
         margin: 10px;
         overflow: auto;
         max-height: 500px;
      }
      div#sujettitre, div#sujettitre * {
         text-align: center;
         font-size: 18px;
         margin-bottom: 25px;
         text-decoration: underline;
      }
      .postbody {
         margin-bottom: 10px;
      }
   </style>
</head>
<body>

<form>
   <input type="url" placeholder="lien du sujet" value="" id="liensujet" name="liensujet" />
   <input type="text" placeholder="sélecteur encodage" value="utf-8" id="selectencodage" />
   <input type="text" placeholder="sélecteur pagination" value="td.pagination span.gensmall" id="selectpag" />
   <input type="text" placeholder="sélecteur titre du rp" value=".catHead h1" id="selecttitre" />
   <input type="text" placeholder="sélecteur post" value="tr.post:not(.post--0)" id="selectpost" />
   <input type="text" placeholder="sélecteur pseudo" value=".name" id="selectpseudo" />
   <input type="text" placeholder="sélecteur message" value=".postbody" id="selectmsg" />
   <button type="button" onclick="charger();">Charger le sujet !</button>
</form>

<div id="pagination"></div>
<div id="sujet">
   <div id="sujettitre"></div>
   <div id="sondage"></div>
   <div id="sujetcontenu"></div>
</div>

<script>

   /**
    * Chargement de la première page
    */
   async function charger() {

      // Lien
      const lien = document.getElementById("liensujet").value;
      const selectencodage = document.getElementById("selectencodage").value;
      const selectpag = document.getElementById("selectpag").value;
      const selecttitre = document.getElementById("selecttitre").value;
      const selectpost = document.getElementById("selectpost").value;
      const selectpseudo = document.getElementById("selectpseudo").value;
      const selectmsg = document.getElementById("selectmsg").value;

      // Chargement de la première page
      const response = await fetch(lien);
      const buffer = await response.arrayBuffer();
      
      // On convertit le format vers utf-8
      const decoder = new TextDecoder(selectencodage);
      const html = decoder.decode(buffer);

      // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');

      // Récupération du titre du sujet
      document.getElementById('sujettitre').replaceChildren();
      const titre = doc.querySelector(selecttitre);
      document.getElementById('sujettitre').appendChild(titre);

      // Récupération du sondage du sujet
      document.getElementById('sondage').replaceChildren();
      const sondage = doc.querySelector('table.poll-result');
      if (sondage){
         document.getElementById('sondage').appendChild(sondage);
      }

      // Récupération des pseudos et messages
      document.getElementById('sujetcontenu').replaceChildren();
      const posts = doc.querySelectorAll(selectpost);
      posts.forEach(function(post) {
         const pseudo = post.querySelector(selectpseudo);
         const contenu = post.querySelector(selectmsg);

         pseudo.classList.add('maNouvelleClassPseudo');
         contenu.classList.add('maNouvelleClassContenu');

         document.getElementById('sujetcontenu').appendChild(pseudo);
         document.getElementById('sujetcontenu').appendChild(contenu);
      });

      // Récupération du nombre de pages du sujet
      let nbPages = 1;
      const pagination = doc.querySelector(selectpag + ' a:nth-last-child(2)');
      if (pagination){
         nbPages = pagination.innerText;
      }

      // Récupération du contenu des autres pages
      for (let i = 1; i < nbPages; i++){

         let lienPage = lien.split('-');
         lienPage[0] = lienPage[0] + "p" + (posts.length * i);
         lienPage = lienPage.join('-');

         // Chargement d'une nouvelle page
         await fetch(lienPage).then(function (response) {
            return response.arrayBuffer();

         }).then(function (bufferPage) {

            // On convertit le format vers utf-8
            const decoderPage = new TextDecoder(selectencodage);
            const htmlPage = decoder.decode(bufferPage);

            // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
            const parserPage = new DOMParser();
            const docPage = parserPage.parseFromString(htmlPage, 'text/html');

            // Récupération des pseudos et messages
            docPage.querySelectorAll(selectpost).forEach(function(postPage) {
               const pseudoPage = postPage.querySelector(selectpseudo);
               const contenuPage = postPage.querySelector(selectmsg);

               pseudoPage.classList.add('maNouvelleClassPseudo');
               contenuPage.classList.add('maNouvelleClassContenu');

               document.getElementById('sujetcontenu').appendChild(pseudoPage);
               document.getElementById('sujetcontenu').appendChild(contenuPage);
            });
         });
      }
   }
</script>
</body>
</html>


Pour les entêtes et numéro de pages, oui, c'est le navigateur qui les rajoute. Il doit y avoir un bouton pour les afficher ou non d'ailleurs. Quant à afficher autre chose, à priori oui, c'est possible, j'ai trouvé ceci qui explique comment faire par exemple : https://prograide.com/pregunta/77663/en-tete-et-pied-de-page-dimpression-html
Toryudo

Toryudo
Aidactif
Aidactif

Masculin
Messages : 1564
Inscrit(e) le : 31/03/2020

https://deus-academia.forumactif.com/
Toryudo a été remercié(e) par l'auteur de ce sujet.

Résolu Re: Enregistrer ou imprimer toutes les pages d'un sujet

Message par MlleAlys Jeu 25 Aoû 2022 - 13:48

ça fonctionne superbement bien !! Merci Toryudo !! sunny

Pour ce qui est des en-têtes et footers, j'avais effectivement vu cette page, je creuserai ça un jour pour savoir s'il est possible d'afficher également le numéro de page (ce que j'ai testé pour l'instant n'a pas fonctionné).
Donc pour l'instant je le passe dans la liste des "bonus possibles un jour peut-être" ! Laughing

Merci encore pour tout ! Je passe le sujet en résolu !

Mon code actuel avec un peu de bidouillage css (pas sûre que ce soit très propre cela dit ^^") pour ceux que cela intéresserait (les champs sont préremplis avec les sélecteurs par défaut pour phpbb2) :
Code:
<!DOCTYPE html>
<html lang="fr" xml:lang="fr">
<head>
  <meta charset="UTF-8" />
  <title>Mon récupérateur de sujet</title>
  <style>
body {
  margin: 1%;
}
form {
  border: 2px solid black;
  padding: 1rem 1%;
  margin: 1rem 0;
  position: sticky;
  background: white;
  top: 0;
}
#sujet {
  border: 1px solid black;
  padding: 1%;
}
#sujettitre, #sujettitre * {
  text-align: center;
  font-size: 2rem;
  margin: 0;
  text-decoration: underline;
}
    h1#sujettitre {
  margin: 1rem 1rem 3rem;
}
.poll-result {
  margin-bottom: 2rem;
}
    .pseudo, .pseudo * {
  font-weight: bold;
  text-decoration: underline;
}
    .contenu {
  margin: 1rem 0 2rem 3%;
}
    .signature_div {
  display: none;
}
    .cont_code {
  font-family: monospace;
}
    .spoiler_content.hidden {
  content-visibility: visible;
}
    .spoiler_title {
  font-weight: bold;
}
    .codebox dd {
  border-left: 1pt solid black;
  padding-left: 0.5rem;
}
   
    @media print {
    form {
        display: none;
      }
    #sujet {
        border: 0;
        max-height: unset;
      }
    }
  </style>
</head>
<body>

<form>
  <input type="url" placeholder="lien du sujet" value="" id="liensujet" name="liensujet" />
  <select id="selectencodage"> <option value="utf-8">utf-8</option> <option value="windows-1252">windows-1252</option> </select>
  <input type="text" placeholder="sélecteur pagination" value=".pagination span" id="selectpag" />
  <input type="text" placeholder="sélecteur titre du rp" value="h1.cattitle" id="selecttitre" />
  <input type="text" placeholder="sélecteur post" value="tr.post:not(.post--0)" id="selectpost" />
  <input type="text" placeholder="sélecteur pseudo" value=".name" id="selectpseudo" />
  <input type="text" placeholder="sélecteur message" value=".postbody" id="selectmsg" />
  <button type="button" onclick="charger();">Charger le sujet !</button>
</form>

<div id="sujet">
  <h1 id="sujettitre"></h1>
  <div id="sondage"></div>
  <div id="sujetcontenu"></div>
</div>

<script>
  /**
    * Chargement de la première page
    */
  async function charger() {

      // Lien
      const lien = document.getElementById("liensujet").value;
      const selectencodage = document.getElementById("selectencodage").value;
      const selectpag = document.getElementById("selectpag").value;
      const selecttitre = document.getElementById("selecttitre").value;
      const selectpost = document.getElementById("selectpost").value;
      const selectpseudo = document.getElementById("selectpseudo").value;
      const selectmsg = document.getElementById("selectmsg").value;

      // Chargement de la première page
      const response = await fetch(lien);
      const buffer = await response.arrayBuffer();
     
      // On convertit le format vers utf-8
      const decoder = new TextDecoder(selectencodage);
      const html = decoder.decode(buffer);

      // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');

      // Récupération du titre du sujet
      document.getElementById('sujettitre').replaceChildren();
      const titre = doc.querySelector(selecttitre);
      document.getElementById('sujettitre').appendChild(titre);

      // Récupération du sondage du sujet
      document.getElementById('sondage').replaceChildren();
      const sondage = doc.querySelector('table.poll-result');
      if (sondage){
        document.getElementById('sondage').appendChild(sondage);
      }

      // Récupération des pseudos et messages
      document.getElementById('sujetcontenu').replaceChildren();
      const posts = doc.querySelectorAll(selectpost);
      posts.forEach(function(post) {
        const pseudo = post.querySelector(selectpseudo);
        const contenu = post.querySelector(selectmsg);

        pseudo.classList.add('pseudo');
        contenu.classList.add('contenu');

        document.getElementById('sujetcontenu').appendChild(pseudo);
        document.getElementById('sujetcontenu').appendChild(contenu);
      });

      // Récupération du nombre de pages du sujet
      let nbPages = 1;
      const pagination = doc.querySelector(selectpag + ' a:nth-last-child(2)');
      if (pagination){
        nbPages = pagination.innerText;
      }

      // Récupération du contenu des autres pages
      for (let i = 1; i < nbPages; i++){

        let lienPage = lien.split('-');
        lienPage[0] = lienPage[0] + "p" + (posts.length * i);
        lienPage = lienPage.join('-');

        // Chargement d une nouvelle page
        await fetch(lienPage).then(function (response) {
            return response.arrayBuffer();

        }).then(function (bufferPage) {

            // On convertit le format vers utf-8
            const decoderPage = new TextDecoder(selectencodage);
            const htmlPage = decoder.decode(bufferPage);

            // On convertit le texte HTML reçu en Objet pour pouvoir le traiter
            const parserPage = new DOMParser();
            const docPage = parserPage.parseFromString(htmlPage, 'text/html');

            // Récupération des pseudos et messages
            docPage.querySelectorAll(selectpost).forEach(function(postPage) {
              const pseudoPage = postPage.querySelector(selectpseudo);
              const contenuPage = postPage.querySelector(selectmsg);

              pseudoPage.classList.add('pseudo');
              contenuPage.classList.add('contenu');

              document.getElementById('sujetcontenu').appendChild(pseudoPage);
              document.getElementById('sujetcontenu').appendChild(contenuPage);
            });
        });
      }
  }
</script>
</body>
</html>

MlleAlys

MlleAlys
Membre actif

Messages : 5967
Inscrit(e) le : 12/09/2012

MlleAlys a été remercié(e) par l'auteur de ce sujet.

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum