[RegExp] Capturer les URL dans une page web
Par Damien ALEXANDRE le vendredi, juillet 11 2008, 20:17 - DevBlog - Lien permanent
Une petite expression régulière sur laquelle j'ai passé du temps, et si je peux éviter ça à quelqu'un via Google ![]()
@<a.*? href=['"]?([^"'\s\>]*)@i
Voilà ce petit pattern est pas non plus über complexe, mais il est over-capable de capturer les URL dans tous les cas imaginables ![]()
- <a href="URL" class="dtc">coucou</a>
- <a id="dtc" href='URL'>coucou</a>
- <a href=URL>coucou</a>
- <a class=dtc HREF=URL id=dtc>coucou</A>
- ...
Bon allez je suis chic, je vais même me fendre d'une explication !
Apprenons les Regex avec tonton Damien
@ le pattern @ le flags
Ici j'ai délimité mon pattern avec des @ (on peux mettre un peu ce qu'on veux), et j'ai mis le flag i, qui veux dire insensible à la casse
(majuscule ou minuscule, il est pas sectaire, il prend tout).
Tout, ou rien
Bon le <a je passe, ça veux dire ce que ça veux dire, mais .*? c'est pas très parlant ![]()
En gros on dit juste qu'il peux y avoir de tout, ou pas
(un class="truc", ou rien).
Puis le href= qui nous sert à identifier où se trouve l'URL.
L'url !
Il faut se la jouer fine, car on peux avoir des ", des ', voir rien du tout pour délimiter notre URL dans l'attribut href.
Alors avec ["']? on dit : ", ', ou pas.
Puis on capture avec une parenthèse parce que l'URL commence ![]()
La fin de l'url alors ?
Avec ([^"'\s\>]*) on dit qu'on capture jusqu'à trouver un ', un ", un espace ou un >.
Vous n'avez rien compris ? Go to http://www.regular-expressions.info/.
/
Commentaires
.*? n'est pas redondant ? Puisque .* signifie "n'importe quel caractère, de 0 à n" et "?" peut-être.
Par contre on peut écrire des liens avec des espaces. C'est pas bien mais on peut
Oncle Tom: '*?' est une forme d'étoile particulière, différente de '*'. En effet, si tu écris une expression régulière comme 'A.*B(.*)C' et que tu la lances sur le texte ABxCByC, le premier '.*' va joyeusement ignorer autant de caractères que possible pour que le B(.*)C ait encore quelque chose à reconnaître. Et donc, ce que les parenthèses reconnaîtront, ce sera 'y' et pas 'x'. Avec 'A.*?B(.*)C', chaque étoile va prendre aussi peu de caractères que nécessaire pour pouvoir reconnaître du B(.*)C, et donc les parenthèses reconnaîtront 'xCBy' et pas 'y'.
Néanmoins, cela pose une question amusante: que se passe-t-il si j'écris dans ma page:
<a name="here-be-anchor"/>
<p href="here-be-URL">Lorem ipsum</p>
La regexp va rencontrer le '<a', puis ignorer tous les caractères jusqu'au ' href=' du paragraphe! Comme quoi, ça n'est pas encore fini
En règle générale, j'utilise plutôt une regexp qui reconnaît des URLs arbitraires, par exemple celle-ci: http://www.manamplified.org/archive...
Merci Victor pour ce commentaire très instructif