scraper html
dionysos19-Jun-2011/22:32:56+2:00
Bonjour à tous,
Je suis nouveau sur le forum.
Après quelques semaines à m'amuser avec rebol, j'ai décidé de m'inscrire. Ca fait plusieurs fois que je suis bloqué sur un même problème et je suis sûr qu'il existe une solution élégante.

J'utilise parse pour récupérer des informations sur des pages web (Allociné).

Voici une illustration de mon problème:
Je recherche à récupérer tous les acteurs d'un film décrit dans le bloc suivant.
<div class="listofmicroviews">
   <div class="datablock">
      <div class="mainzone microview">
         <div class="picturezone">
            <a href="/personne/fichepersonne_gen_cpersonne=18851.html">
            <img src="http://images.allocine.fr/r_60_80/medias/nmedia/18/35/26/44/18909519.jpg" alt="Elijah Wood" title="Elijah Wood"></a>
         </div><!-- /picturezone -->
         <div class="contenzone">
            <div class="titlebar">
               <h3>
                  <a href="/personne/fichepersonne_gen_cpersonne=18851.html">Elijah Wood</a>
               </h3>
            </div>
            <p>
            Rôle : Frodon Sacquet
            </p>
            <div class="spacer"></div>
         </div><!-- /contenzone -->
         <div class="spacer"></div>
      </div>
   </div><!-- /datablock -->
   <div class="datablock">
   [...]
   </div>
   <div class="datablock">
   [...]
   </div>
</div>

Je voudrais trouver la règle de parsing qui permet de récupérer un sous-bloc complet comme:
<div class="contenzone">
   <div class="titlebar">
      <h3>
         <a href="/personne/fichepersonne_gen_cpersonne=18851.html">Elijah Wood</a>
      </h3>
   </div>
   <p>
   Rôle : Frodon Sacquet
   </p>
   <div class="spacer"></div>
</div><!-- /contenzone -->
   
L'idée c'est d'extraire un sous bloc moins complexe pour en extraire les informations et continuer avec le sous bloc suivant.

Le problème c'est que je ne sais pas associé un tag de début avec un tag de fin.
J'ai essayé avec un compteur qui est incrémenté/décrémenté à chaque tag div.
Mais je n'y arrive pas.
Dans l'implémentation, je ne veux pas tenir compte de la structure de cette page et me reposer dessus pour extraire les informations, je voudrais que ce soit généraliste.
J'ai pas explorer de piste avec load/markup... Actuellement je fais mon parser en mode string.
Merci pour votre aide.
guest220-Jun-2011/12:05:24+2:00
Hmm... à première vue la règle est super simple si tu connais le tag de début et le tag de fin.
[
to {<div class="contenzone">} ;; tag début 
copy sub-bloc
thru {</div><!-- /contenzone -->} ;; tag de fin
]


Alors j'imagine que ce que tu veux faire est plus compliqué. (d'ailleurs j'ai pas bien compris pourquoi tu devais compter les tags <div>).
Montre nous ta règle actuelle, on comprendra mieux où tu veux en venir.
dionysos20-Jun-2011/12:39:40+2:00
Mon but étant que ce soit générique, je ne voudrais pas me baser sur les commentaires de fin de sections comme <!-- /contenzone --> puisque s'agissant d'un commentaire, on ne peut pas compter sur sa présence.

Et dans ce cas ça devient plus compliqué à parser.
En faisant
[
thru {</div> ;; tag de fin
]
tu vas aller jusqu'à un tag de fin mais pas forcément celui associé à ton tag de début dans le cas de div imbriqués.

D'où l'idée de compter les ouvertures et fermetures de sections pour savoir les appareiller.

J'ai trouvé un début de solution en utilisant et m'inspirant du script parseen.r
dionysos20-Jun-2011/12:40:27+2:00
comment faut il faire pour insérer du code avec la mise en forme qui convient?
dionysos20-Jun-2011/14:33:36+2:00
J'espère que c'est pas trop illisible!
Ca fonctionne presque, mais c'est pas encore ça...

open-close-counter: 0
main-open-close-counter: 0
fail: [end skip] ; règle pour sortir d'une boucle (je pense que mon problème restant vient de là)
leave: none
main-leave: none

exit-loop: func [
	"exit from a parse loop"
	cnt
	'exit?
][
	either cnt = 0 
	[
		set exit? fail
		print ["BREAK" exit?]
	][
		set exit? none
	]
]

mainzone-microview-tags: thru-rule [dbg: (probe copy/part dbg 20)
	{</div>} (
		open-close-counter: open-close-counter - 1
		print [ "*close" main-open-close-counter open-close-counter ]
		exit-loop open-close-counter leave
	) |
	{<div} (
		open-close-counter: open-close-counter + 1
		print [ "*open " main-open-close-counter open-close-counter]
		exit-loop open-close-counter leave
	)
]

datablock-tags: thru-rule [dbg: (probe copy/part dbg 20)
	{</div>} (
		main-open-close-counter: main-open-close-counter - 1
		print [ "close " main-open-close-counter open-close-counter ]
		exit-loop main-open-close-counter main-leave
	) |
	{<div class="datablock">}  (
		main-open-close-counter: main-open-close-counter + 1 
		print [ "open  " main-open-close-counter open-close-counter]
		exit-loop main-open-close-counter main-leave
	) 
	some [mainzone-microview-tags stop: leave ] (print "exit") |
	"^/" (print "trash eol")
]


parse reply [
	thru tag 
	thru {<div class="listofmicroviews">} (main-open-close-counter: main-open-close-counter + 1)
	some [
		datablock-tags start: main-leave 
	] (print ["leave all loops" main-open-close-counter main-leave leave])
]	


Grosso modo, il y a une section "listofmicroviews" qui contient des "datablock".
Quand le parser détecte qu'il faut sortir de mainzone-microview-tags (leave passé à fail), le parser retourne dans la règle datablock-tags.
Ce que je constate en debugant, c'est que le curseur du parser dans le buffer est revenu en arrière et donc je parse 2 fois un </div> au lieu d'une seule fois normalement provoquant la sortie de la boucle principale "listofmicroviews" alors que d'autres "datablock" sont présents.

J'espère que c'est à peu près clair.
Si vous voyez d'autres façon de faire je suis preneur, car ça commence à ressembler à une usine à gaz!
guest220-Jun-2011/15:03:51+2:00
J'ai pas trop lu ton code mais voici une solution avec une règle récursive pour éviter les tags <div> imbriqués(ce qui évite l'usage d'un compteur).

skip-div: [
	some [
		  "<div " skip-div "</div>"
		| p: "</div>" :p break 
		| skip to #"<"
	]
]

parse src [
	thru {<div class="contenzone">}
	copy sub skip-div 
	(print sub)
]


et la même règle mais pour R3.
skip-div: [
	some [
		  "<div " skip-div "</div>"
		| and "</div>" break
		| skip to #"<"
	]
]
dionysos20-Jun-2011/15:10:53+2:00
Génial!
Je viens d'essayer ta solution (R2), ça fonctionne.
Je n'ai plus qu'à analyser ce que tu proposes pour bien comprendre.
Merci beaucoup.
trigram21-Jun-2011/16:41:19+2:00
guest2 pourrais-tu détailler un peu ta solution ?

D'avance merci.
dionysos22-Jun-2011/20:25:49+2:00
Oui je veux bien quelques explications...

skip-div: [
	some [
		  "<div " skip-div "</div>"
		| p: "</div>" :p break      ; <= Ce </div> correspond à la fermeture de la section <div class="contenzone"> ? C'est à dire le
                                            ;    dernier div.
                                            ;    Comment le marqueur p: capture depuis le début de la section <div class="contenzone"> ?
                                            ;    Peux tu donner plus d'explications du fonctionnement de p: :p ?
		| skip to #"<"              
	]
]


copy sub skip-div ; j'en déduis l'on retrouve dans sub tout ce qui match la règle skip-div


La plupart des exemples que j'ai vu avec copy était
copy sub to "un token terminal"
copy sub thru "un token terminal"

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2