Myrville a écrit :
[...] les problèmes liés à certains caractères Unicode. [...]
En effet, la bibliothèque RegularExpression ne gère pas correctement les caractères Unicode codés sur plus de deux octets et plus particulièrement la fonction RegularExpressionMatchLength().
Le recours à cette bibliothèque pour l'analyse des balises HTML se révèle des plus pertinents dès lors que l'on est certain de ne pas être confronté à cette problématique sinon, à moins d'une alternative que j'ignore, il convient de passer par une gestion purement textuelle, ce qui est plus chiant.
Myrville a écrit :
Dans mon cas l’idée n’est pas forcément de refaire un outil aussi complet, mais plutôt de récupérer certaines informations simples dans une page (par exemple les balises de titres ou certains attributs). Du coup je me demandes encore, avec le recul, si danss ce cas précis on peut repartir toujours sur une approche RegEx pour ce type d’analyse ou on peut privilégier aujourd’hui une autre méthode.
Je ne sais pas quel est ton but précis mais ci-dessous un petit exemple qui affiche les sections et sous-sections du forum PB anglais :
Code : Tout sélectionner
EnableExplicit
; ╔═════════════════════════════════════════════════════════════════════════════╗
; ║ STRUCTURES - ENUMERATIONS - CONSTANTES - MACROS - MAPS - VARIABLES GLOBALES ║
; ╚═════════════════════════════════════════════════════════════════════════════╝
;{ ════ ENUMERATIONS ════
;- ════ ENUMERATIONS
Enumeration RegEx
#REGEX_HTMLBAL
#REGEX_CSID
EndEnumeration
;}
;{ ════ CONSTANTES ════
;- ════ CONSTANTES
#HTML_REGEXHTMLBAL="</?\w+:?\w*((\s+(\w+-?+)+:?\w?+(\s*=\s*(?:"+#DQUOTE$+".*?"+#DQUOTE$+"|'.*?'|[^'"+#DQUOTE$+">\s]+))?)+\s*|\s*)/?>"
#HTML_REGEXCSID="(?i)-[\d\w]{8}(-[\d\w]{4}){3}-[\d\w]{12}$"
;}
;-══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
; ╔════════════╗
; ║ PROCEDURES ║
; ╚════════════╝
Procedure.s Fc_Recuperation_DonneesHTMLRequeteHTTP(ArgRequeteHTTP.s,ArgMode=#PB_UTF8)
Protected.i IDRequeteHTTP
Protected.s TitreMSG="Requête HTTP",Statut,TexteHTML
IDRequeteHTTP=HTTPRequest(#PB_HTTP_Get,ArgRequeteHTTP)
If IDRequeteHTTP
Statut=HTTPInfo(IDRequeteHTTP,#PB_HTTP_StatusCode)
If Statut="200"
TexteHTML=HTTPInfo(IDRequeteHTTP,#PB_HTTP_Response,ArgMode)
FinishHTTP(IDRequeteHTTP)
ProcedureReturn TexteHTML
ElseIf Statut<>"0" And Statut<>"404"
MessageRequester(TitreMSG,UnescapeString("Erreur lors du retour de la requête :\n\nCode : "+Statut+"\n\n"+ArgRequeteHTTP),#PB_MessageRequester_Error)
EndIf
Else
MessageRequester(TitreMSG,UnescapeString("Echec de la requête\n\n"+ArgRequeteHTTP),#PB_MessageRequester_Error)
EndIf
EndProcedure
Procedure Pc_Recuperation_DonneesChaineHTML_ListeSectionsForum(ArgChaineHTML.s)
;{ Variables obligatoires
Protected.i AncPosition=1 ; Position précédente dans la variable TexteFichier
Protected.i NouvPosition ; Position actuelle dans la variable TexteFichier après appel RegEx
Protected.i LongChaine ; Longueur de la chaine textuelle entre deux balises
Protected.a Commentaire ; Commentaire HTML en cours de traitement (Booléen)
Protected.s ChaineHTML ; Contenu balise HTML ou Contenu entre deux balises
Protected.s ChaineHTMLModifiee ; ChaineFichier expurgée des espaces
;}
Protected.a BaliseTableTrouvee
Protected.a BaliseSectionForumTrouvee
Protected.a BaliseTitreSectionTrouvee
Protected.a BaliseForumTrouvee
Protected.a BaliseDetailsForumTrouvee
Protected.a BaliseTitreForum
Protected.a NoLigneInformation
CreateRegularExpression(#REGEX_CSID,#HTML_REGEXCSID,#PB_RegularExpression_NoCase)
; Suppression des LF, CR & TAB
CompilerIf #PB_Compiler_Version<=630
ReplaceString(ArgChaineHTML,Chr(10)," ",#PB_String_InPlace)
ReplaceString(ArgChaineHTML,Chr(13)," ",#PB_String_InPlace)
ReplaceString(ArgChaineHTML,Chr(9)," ",#PB_String_InPlace)
CompilerElse
ArgChaineHTML=ReplaceString(ReplaceString(ReplaceString(ArgChaineHTML,Chr(10)," "),Chr(13)," "),Chr(9)," ")
CompilerEndIf
ArgChaineHTML=Trim(ArgChaineHTML)
; Test entête fichier HTML
If UCase(Left(ArgChaineHTML,15))<>"<!DOCTYPE HTML>" ; ← A adapter en fonction de l'entête de la page HTML
MessageRequester("Analyse Balises et attributs HTML","Le fichier ne semble pas être un fichier HTML",#PB_MessageRequester_Error)
ProcedureReturn
EndIf
; Boucle lecture des balises
If CreateRegularExpression(#REGEX_HTMLBAL,#HTML_REGEXHTMLBAL)
If ExamineRegularExpression(#REGEX_HTMLBAL,ArgChaineHTML)
While NextRegularExpressionMatch(#REGEX_HTMLBAL)
NouvPosition=RegularExpressionMatchPosition(#REGEX_HTMLBAL)
; Analyse du contenu entre deux balises ou commentaires HTML "<!-- blabla -->"
If AncPosition<>NouvPosition ; Texte ou commentaire
LongChaine=NouvPosition-AncPosition
ChaineHTML=Mid(ArgChaineHTML,AncPosition,LongChaine) ; ATTENTION : Ajout de +1 pour compenser un caractère Unicode dans l'en-tête
If Left(LTrim(ChaineHTML),4)="<!--" ; Balise début commentaire
If Right(RTrim(ChaineHTML),3)<>"-->" ; Commentaire encadrant:"<!-- blabla > <blabla> blabla <!-->"
Commentaire=#True
EndIf
ElseIf Right(RTrim(ChaineHTML),3)="-->" ; Balise fin commentaire encadrant
Commentaire=#False
ElseIf BaliseTableTrouvee
If BaliseTitreSectionTrouvee
Debug "Section du forum : "+ChaineHTML
BaliseSectionForumTrouvee=#False:BaliseTitreSectionTrouvee=#False ; On n'a plus besoin pour le moment de ces balises
ElseIf BaliseTitreForum
ChaineHTML=Trim(ChaineHTML)
If ChaineHTML
Select NoLigneInformation
Case 0
Debug " Titre du forum : "+ChaineHTML
NoLigneInformation+1
Case 1
Debug " Description du forum : "+ChaineHTML
NoLigneInformation=0
BaliseTitreForum=#False ; On n'a plus besoin pour le moment de cette balise et on s'évite ainsi des tests ultérieurs inutiles
EndSelect
EndIf
EndIf
EndIf
EndIf
; Analyse balise HTML
LongChaine=RegularExpressionMatchLength(#REGEX_HTMLBAL)
ChaineHTML=RegularExpressionMatchString(#REGEX_HTMLBAL)
If Left(ChaineHTML,19)="<div id="+Chr(34)+"page-body"+Chr(34) ; Balise table sections forum
BaliseTableTrouvee=#True
ElseIf BaliseTableTrouvee
If ChaineHTML="</ul>" ; Balise fin section forum
ElseIf ChaineHTML="<ul class="+Chr(34)+"topiclist"+Chr(34)+">" ; Balise section forum
BaliseSectionForumTrouvee=#True
ElseIf BaliseSectionForumTrouvee
If Left(ChaineHTML,27)="<a href="+Chr(34)+"./viewforum.php?f=" ; Balise lien hypertexte section comportant le nom de la section
BaliseTitreSectionTrouvee=#True
EndIf
ElseIf ChaineHTML="<ul class="+Chr(34)+"topiclist forums"+Chr(34)+">" ; Balise section forum
BaliseForumTrouvee=#True
ElseIf BaliseForumTrouvee
If ChaineHTML="<dl class="+Chr(34)+"row-item forum_read"+Chr(34)+">"
BaliseDetailsForumTrouvee=#True
ElseIf BaliseDetailsForumTrouvee
If Left(ChaineHTML,27)="<a href="+Chr(34)+"./viewforum.php?f="
BaliseTitreForum=#True
EndIf
EndIf
ElseIf ChaineHTML="<form method="+Chr(34)+"post" +Chr(34)+"action="+Chr(34)+"./ucp.php?mode=login" +Chr(34)+"class="+Chr(34)+"headerspace panel"+Chr(34)+">"
; On n'a pas besoin d'analyser plus loin
Break
EndIf
EndIf
AncPosition=NouvPosition+LongChaine
Wend
EndIf
EndIf
EndProcedure
;
Define.s ChaineHTMML=Fc_Recuperation_DonneesHTMLRequeteHTTP("https://www.purebasic.fr/english/index.php")
If ChaineHTMML
Pc_Recuperation_DonneesChaineHTML_ListeSectionsForum(ChaineHTMML)
EndIf