REGEX et parsing HTML [Résolu]

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

REGEX et parsing HTML [Résolu]

Message par Kwai chang caine »

Bonjour à tous

Je suis tombé sur un super code de "Deluxe0321" qui parsait de l'HTML avec des REGEX (Cool l'idée) 8)
Seulement voilà, il ne parse "que" les attributs et les balises, pas le texte des balises :|
Les passionnés des REGEX (comment est ce possible :mrgreen:) sauraient il comment récupérer le texte plutôt que l'attribut des balises ?

Code : Tout sélectionner

AExpression.s = "(\S+)=["+#DQUOTE$+"']?((?:.(?!["+#DQUOTE$+"']?\s+(?:\S+)=|[>"+#DQUOTE$+"']))+.)["+#DQUOTE$+"']?"

Code : Tout sélectionner

<MaBalise>Je cherche à récupérer ce texte</MaBalise>

Code : Tout sélectionner

InitNetwork()
;// html tag expression --> http://haacked.com/archive/2004/10/25/usingregularexpressionstomatchhtml.aspx
Expression.s = "</?\w+((\s+\w+(\s*=\s*(?:"+#DQUOTE$+".*?"+#DQUOTE$+"|'.*?'|[^'"+#DQUOTE$+">\s]+))?)+\s*|\s*)/?>"

;// html attribute expression -->  http://stackoverflow.com/a/317081
AExpression.s = "(\S+)=["+#DQUOTE$+"']?((?:.(?!["+#DQUOTE$+"']?\s+(?:\S+)=|[>"+#DQUOTE$+"']))+.)["+#DQUOTE$+"']?"

RegEx.i  = CreateRegularExpression(#PB_Any,Expression.s)
ARegEx.i = CreateRegularExpression(#PB_Any,AExpression.s)

If RegEx.i and ARegEx.i
 
  If ReceiveHTTPFile("http://www.purebasic.fr/english/", GetHomeDirectory()+"tmp.html")
   
    If OpenFile(0,GetHomeDirectory()+"tmp.html")
      *mem = AllocateMemory(Lof(0))
      If *mem
        ReadData(0,*mem,Lof(0))
        CloseFile(0)
      EndIf
      DeleteFile(GetHomeDirectory()+"tmp.html")
    EndIf
   
    Content.s = PeekS(*mem,-1,#PB_Ascii)
    FreeMemory(*mem)
    Debug Content.s
   
    Dim Arr.s(0)
    Dim AArr.s(0)
   
    ArrSize.i = ExtractRegularExpression(RegEx.i,Content.s,Arr())
    If ArrSize.i
      Debug "Found "+Str(ArrSize.i)+" HTML Tags:"
     
      For i=0 To ArrSize.i - 1
       
        ReDim AArr(0)
       
        AArrSize.i = ExtractRegularExpression(ARegEx.i,Arr(i),AArr())
       
        Debug Space(4) + "HTML-Tag:"
        Debug Space(8) + Arr(i)
       
        If AArrSize
          Debug Space(4) + "Attributes: "
          For i2 = 0 To AArrSize.i - 1
            Debug Space(8) + AArr(i2) 
          Next
        EndIf
       
      Next
    EndIf
  EndIf
EndIf
Merci et bonne journée
Dernière modification par Kwai chang caine le sam. 07/juil./2018 9:06, modifié 1 fois.
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: REGEX et parsing HTML

Message par Ar-S »

Salut KCC
Tu veux procéder par regex ?
Parce qu'une petite procédure de findstring() pourrait suffire vu que les textes sont... Balisés !

En attendant, évitons de polluer l'ordi avec des fichiers temp maintenant qu'on a ReceiveHTTPMemory().

Remplace

Code : Tout sélectionner

If ReceiveHTTPFile("http://www.purebasic.fr/english/", GetHomeDirectory()+"tmp.html")
   
    If OpenFile(0,GetHomeDirectory()+"tmp.html")
      *mem = AllocateMemory(Lof(0))
      If *mem
        ReadData(0,*mem,Lof(0))
        CloseFile(0)
      EndIf
      DeleteFile(GetHomeDirectory()+"tmp.html")
    EndIf
   
    Content.s = PeekS(*mem,-1,#PB_Ascii)
    FreeMemory(*mem)
    Debug Content.s
par

Code : Tout sélectionner

 *Buffer = ReceiveHTTPMemory("http://www.purebasic.fr/english//index.php")
   
    If *Buffer
      Taille = MemorySize(*Buffer)
      Content.s = PeekS(*Buffer, Taille, #PB_Ascii)
     
    FreeMemory(*Buffer)
    Debug Content.s
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: REGEX et parsing HTML

Message par Kwai chang caine »

Bonjour ARS :D

Bah disons que j'ai trouvé ce code assez performant pour sa petitesse 8O
J'ai lu que l'on ne peut pas faire de la perfection avec les REGEX pour ce qui est du HTML, mais ce code s'en tire pas mal 8)
Alors je me suis dit que c'était dommage que la demande initiale n'était que sur les attributs, car avec les textes il aurait été assez complet.
Maintenant c'est sûr qu'utiliser ce genre de code, c'est fatalement rendre les aficionados des REGEX indispensables :lol:
Mais comment peut on pouvoir répondre à ma question sans user 3 boites de cachets et risquer une année de dépression :lol:
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: REGEX et parsing HTML

Message par Ar-S »

Un ancien code de G-Rom pour extraire entre les balises.

Code : Tout sélectionner

Procedure.s ExtractFromTag(Text.s, open.s, close.s)
  PosA = FindString(Text,open,1) + Len(open)
  PosB = FindString(Text,close,2)
  Out$ = Mid(Text,PosA,PosB-PosA)
  ProcedureReturn Out$
EndProcedure



REGEX_MASK_H_1_6$     = "<h([1-6])>([^<]*)</h([1-6])>"
REGEX_MASK_STRONG$    = "<strong>([^<]*)</strong>"
REGEX_MASK_PROCEDURE$ = "Procedure([^<]*)\)"



n$ = "<h1>This is a crappy tag</hx>"
n$ + "<h1>This is a good title !</h1>"
n$ + "<h1>this bad tag is bypass the regex </hc>"
n$ + "<strong>HARD BYTE!</strong>"
n$ + "<strong>HARD BYTE! second time</strong>"
n$ + "<BadTag>DUR COMME MA BYTE!</BadTag>"
n$ + "Prcocedure Test(A.f)"
n$ + "Procedurdes Floo(A.f)"
n$ + "Procedure Floo(A.f)"

;-Extraction des titres :
exp = CreateRegularExpression(#PB_Any,REGEX_MASK_H_1_6$)
Dim Titre$(0)
TitreFound = ExtractRegularExpression(exp,n$, Titre$())
FreeRegularExpression(exp)

;-Extraction des strong :
exp = CreateRegularExpression(#PB_Any,REGEX_MASK_STRONG$)
Dim Strong$(0)
StrongFound = ExtractRegularExpression(exp,n$, Strong$())
FreeRegularExpression(exp)   

;-Extraction des procedures :
exp = CreateRegularExpression(#PB_Any,REGEX_MASK_PROCEDURE$)
Dim Proc$(0)
ProcFound = ExtractRegularExpression(exp,n$, Proc$())
FreeRegularExpression(exp)   



Debug "Good Title :"
For k = 0 To TitreFound-1
	Debug "- "+ExtractFromTag(Titre$(k),"<h1>","</h1>")
Next
Debug "Strong & Ok :"
For k = 0 To StrongFound-1
	Debug "- "+ExtractFromTag(Strong$(k),"<strong>","</strong>")
Next
Debug "Good Proce :"
For k = 0 To ProcFound-1
	Debug "- "+Proc$(k)
Next
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: REGEX et parsing HTML

Message par Ollivier »

Code : Tout sélectionner

;**************************************************************************************************************
Procedure.S Up(C.S, M.S)
 A = FindString(C, ">", FindString(C, "<" + M, 1, #PB_String_NoCase) ) + 1
 ProcedureReturn Mid(Content, A, FindString(C, "</" + M, A, #PB_String_NoCase) - A)
EndProcedure

Debug Up(Content, "HEAD")
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: REGEX et parsing HTML

Message par Ollivier »

(

1) tolère la casse différentiée
2) tolère les espaces post-balise
3) tolère la présence de membres au sein des balises
4) tolère les caractères de balise inter-balise
5) tolère les entrelacements de balise

Norme W3C (Liens directs et version française traduite par mes soins en section Hors-Sujet)

)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: REGEX et parsing HTML

Message par Kwai chang caine »

Waoouh !!! 8O

@Ars
J'étais passé à coté de ce code et pourtant c'est pas faute de hanter les forums toute la journée :oops:
Il marche apparemment nickel, je testerais sur les pages que je dois parser

Code : Tout sélectionner

n$ + "<BadTag>DUR COMME MA BYTE!</BadTag>"
On reconnait bien la signature de notre G-Rom national :lol:
Merci beaucoup ARS 8)

@Ollivier
Merci pour ton code mais il ne fonctionne pas :|
J'ai du remplacé la variable "content" par "C" si j'ai bien compris :|
De plus, on est obligé apparemment il ne remonte pas le bon texte, ni avec le HTML bidon de GRom, ni avec le HTML du site PB de ARS :|

Code : Tout sélectionner

n$ = "<h1>This is a crappy tag</hx>"
n$ + "<h1>This is a good title !</h1>"
n$ + "<h1>this bad tag is bypass the regex </hc>"
n$ + "<strong>HARD BYTE!</strong>"
n$ + "<strong>HARD BYTE! second time</strong>"
n$ + "<BadTag>DUR COMME MA BYTE!</BadTag>"
n$ + "Prcocedure Test(A.f)"
n$ + "Procedurdes Floo(A.f)"
n$ + "Procedure Floo(A.f)"

Procedure.S Up(C.S, M.S)
A = FindString(C, ">", FindString(C, "<" + M, 1, #PB_String_NoCase) ) + 1
ProcedureReturn Mid(C, A, FindString(C, "</" + M, A, #PB_String_NoCase) - A)
EndProcedure

InitNetwork()
*Buffer = ReceiveHTTPMemory("http://www.purebasic.fr/english//index.php")
   
If *Buffer
  Taille = MemorySize(*Buffer)
  Content.s = PeekS(*Buffer, Taille, #PB_Ascii)
 
 FreeMemory(*Buffer)
 ;Debug Up(Content$, "")
 
EndIf 

Debug Up(Content, "HEAD")
Quoi qu'il en soit, merci à vous deux !!!! 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: REGEX et parsing HTML [Résolu]

Message par Ollivier »

@Ollivier
Mercipour ton code maisil ne fonctionnepas
J'ai du remplacéla variable"content" par "C" si j'ai biencompris
C'est une bonne réponse. Kcc n'est pas content. Car, malgré ses soins délicats, la défroqueuse de page HTML ne fonctionne pas.
Marc56
Messages : 2146
Inscription : sam. 08/févr./2014 15:19

Re: REGEX et parsing HTML [Résolu]

Message par Marc56 »

Si ta page ne contient que du HTML de base, il suffit de prendre ce qui est entre > et <

Code : Tout sélectionner

If CreateRegularExpression(0, "\>(.+)\<")
    If ExamineRegularExpression(0, "<MaBalise>Je cherche à récupérer ce texte</MaBalise>")
        While NextRegularExpressionMatch(0)
            Debug RegularExpressionGroup(0, 1)
        Wend
    EndIf
Else
    Debug RegularExpressionError()
EndIf

Code : Tout sélectionner

Je cherche à récupérer ce texte
Mais, maintenant, la plupart des pages HTML étant infestées de css, javascript, flash, truc pour le bling-bling et autres s.....peries pour imposer de la pub, ça devient quasi impossible de faire un filtre efficace.
Cette regex va par exemple exclure le javascript, donc le texte qui a été généré par lui selon l'action utilisateur.

Si ta page est une page statique ou générée par le serveur (ex: PHP ou CGI), alors le code est filtrable puisque le navigateur ne reçoit que le produit du script.

Si c'est juste du HTML "normal" de la grande époque (c'est à dire conçu pour être lu par tout le monde et même avec un navigateur texte comme Lynx), alors donne-moi une url et le te fais la RegEx qui ira bien.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: REGEX et parsing HTML [Résolu]

Message par Kwai chang caine »

Merci beaucoup Marc 8)

Ton code marche déjà pas mal, mais tu dois t'en douter il en remonte plus que prévu :wink:
La bonne nouvelle, c'est que c'est du "vebe" de chez "vebe" pas de pubs à la con, juste du JS pour faire joli, mais vraiment limité au max, c'est pour le boulot, et on rigole pas au boulot :cry:
Donc le problème c'est que ce sont des pages intranets, inaccessibles de l’extérieur, mais surtout blindées d'informations confidentielles de clients ou de ma boite :|

C'est pas aussi simple que après les ">" et avant les "<" car il y a des tableaux ...
Par contre, je peux te donner un extrait dans lesquels je cherche à retourner le texte
29276985
45 AVENUE ROSA PARKS
A
RDC

69009 LYON
000000000000
11111111
En service
BOUDOU JEAN-CLAUDE

Code : Tout sélectionner

[code]<tbody>
<tr class="odd">
<td style="width: 110px;"><a id="lien" class="buttonDoAfficher" href="/Portail/appmanager/portail/bureau?_nfpb=true&_windowLabel=lFiche_2&_pageLabel=_page_rechercherUnPoint&wsrp-urlType=blockingAction&wsrp-secureURL=true&wsrp-url=&wsrp-requiresRewrite=&wsrp-navigationalValues=&wsrp-navigationalState=eJyLL07OO0i1Pc-JT0rMYYNQtgBZ6Cf8&wsrp-interactionState=wlplFiche_2_id%3E29276985%26wlplFiche_2_action%3Dtrouver%26wlplFiche_2_criteresRecherche%3DcriteresRechercheValue&wsrp-mode=&wsrp-windowState=&">29276985</a></td>
<td style="max-width: 180px;">45 AVENUE ROSA PARKS</td>
<td style="width: 58px;">A</td>
<td style="width: 75px;">RDC</td>
<td style="width: 58px;"></td>
<td style="width: 58px;">69009 LYON</td>
<td style="width: 95px;" class="NumSerie">000000000000</td>
<td style="width: 58px;" class="type">11111111</td>
<td style="width: 65px;" class="etat">En service</td>
<td style="width: 110px;" class="nomClient">BOUDOU JEAN-CLAUDE</td></tr>
<tr class="even">
Le même bloc se reproduit et fini par </tbody> à la toute fin
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Marc56
Messages : 2146
Inscription : sam. 08/févr./2014 15:19

Re: REGEX et parsing HTML [Résolu]

Message par Marc56 »

À l'arrache (et pour une seule ligne pour l'instant) le reste demain.
Mets ton fichier html dans data.txt
La RegEx est moche mais c'est ̶ ̶p̶a̶r̶c̶e̶ ̶q̶u̶e̶ ̶j̶'̶a̶i̶ ̶l̶a̶ ̶f̶l̶e̶m̶m̶e̶ ̶d̶e̶ ̶r̶o̶u̶v̶r̶i̶r̶ ̶l̶a̶ ̶d̶o̶c̶ ̶p̶a̶r̶c̶e̶ ̶q̶u̶'̶i̶l̶ ̶f̶a̶i̶t̶ ̶t̶r̶o̶p̶ ̶c̶h̶a̶u̶d̶ pour la compréhension
Seul le début est différent, ensuite je copie/colle .+>(.*)</td> 9 fois

Code : Tout sélectionner

EnableExplicit

; Données à trouver
;
; 29276985
; 45 AVENUE ROSA PARKS
; A
; RDC
; 
; 69009 LYON
; 000000000000
; 11111111
; En service
; BOUDOU JEAN-CLAUDE

Enumeration 
    #hFile  
    #RegEx
EndEnumeration

; --- Load datafile
If Not ReadFile(#hFile, "Datas.txt")
    MessageRequester("Error", "No data file")
    End
EndIf

Define Txt$ 
While Not Eof(#hFile)
    Txt$ = ReadString(#hFile, #PB_File_IgnoreEOL)
Wend    
CloseFile(#hFile)
; --- 

Define RegEx$ = ~"&\">(.+)</a></td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>.+>(.*)</td>"

If CreateRegularExpression(#RegEx, RegEx$, #PB_RegularExpression_DotAll)
    If ExamineRegularExpression(#RegEx, Txt$)
        Define Nb_Cols = CountRegularExpressionGroups(#RegEx)
        Define i.a
        While NextRegularExpressionMatch(#RegEx)
            For i = 1 To 10  
                Debug "" + RSet(Str(i), 2, " ") + ": " + RegularExpressionGroup(#RegEx, i)
            Next    
        Wend
        
    EndIf
Else
    Debug RegularExpressionError()
EndIf

End

Code : Tout sélectionner

 1: 29276985
 2: 45 AVENUE ROSA PARKS
 3: A
 4: RDC
 5: 
 6: 69009 LYON
 7: 000000000000
 8: 11111111
 9: En service
10: BOUDOU JEAN-CLAUDE
Ça fonctionne, à condition qu'aucun champ ne contienne de < > auquel cas, il faut isoler un peu plus en augmentant les caractères devant et derrière chaque group ()
Le group () est répété 10 fois pour qu'il sorte quelque-chose même si le champs est vide.

:wink:
Marc56
Messages : 2146
Inscription : sam. 08/févr./2014 15:19

Re: REGEX et parsing HTML [Résolu]

Message par Marc56 »

Kwai chang caine a écrit :Le même bloc se reproduit et fini par </tbody> à la toute fin
Après, soit on fait une regex plus compliquée, soit on bouche en faisant une nouvelle chaine à chaque <tbody></tbody> ou <tr></tr>
(c'est sans doute le plus simple)
Marc56
Messages : 2146
Inscription : sam. 08/févr./2014 15:19

Re: REGEX et parsing HTML [Résolu]

Message par Marc56 »

Et pour entrer les données dans un fichier CSV ou une base SQL, tu insère les commandes SQL ou code dans la boucle

Code : Tout sélectionner

            For i = 1 To 10 
                Debug "" + RSet(Str(i), 2, " ") + ": " + RegularExpressionGroup(#RegEx, i)
            Next 
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: REGEX et parsing HTML [Résolu]

Message par Kwai chang caine »

Merci beaucoup Marc56
Mais je pensais pas que ce serait si compliqué à faire 8O
Etant donné que le précédent code marchait pas trop mal pour les attributs et les balises, je pensais qu'il fallait juste modifier un peu le REGEX des attributs pour obtenir les textes
J'ai lancé ton code et les style et class remontent aussi

Code : Tout sélectionner

<td style="max-width: 180px;">

Code : Tout sélectionner

<td style="width: 110px;" class="nom">Kiki la houpette</td></tr>
<tr class="even">
Bon te casse pas plus la tête, si c'est si compliqué, je passerais par le parsing traditionnel ou j'utiliserais le code de Grom
Je voudrais pas que tu surchauffe :lol:

Quoi qu'il en soit, je te remercie déjà mille fois d'avoir pris le temps de m'aider 8) 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: REGEX et parsing HTML [Résolu]

Message par Ollivier »

Kcc,

quand tu rentres dans une cabine d'essayage, on enlève les pantalons au fur et à mesure, on n'accumule pas les pantalons les uns sur les autres, sinon, au bout de 3 pantalons, on ne peut plus plier un genou sans s'exploser les grelots...
Répondre