Page 1 sur 2

REGEX et parsing HTML [Résolu]

Publié : ven. 06/juil./2018 20:05
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

Re: REGEX et parsing HTML

Publié : ven. 06/juil./2018 20:24
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

Re: REGEX et parsing HTML

Publié : ven. 06/juil./2018 21:19
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:

Re: REGEX et parsing HTML

Publié : ven. 06/juil./2018 23:13
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

Re: REGEX et parsing HTML

Publié : ven. 06/juil./2018 23:24
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")

Re: REGEX et parsing HTML

Publié : ven. 06/juil./2018 23:46
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)

)

Re: REGEX et parsing HTML

Publié : sam. 07/juil./2018 9:05
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)

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 10:12
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.

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 10:22
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.

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 11:16
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

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 17:23
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:

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 17:34
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)

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 17:37
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 

Re: REGEX et parsing HTML [Résolu]

Publié : sam. 07/juil./2018 18:16
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)

Re: REGEX et parsing HTML [Résolu]

Publié : dim. 08/juil./2018 10:16
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...