Essayer de trouver les liens sur une page.
mon regex est:
/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/
mais semble échouer à
<a title="this" href="that">what?</a>
Comment pourrais-je changer mon regex pour traiter avec href pas placé en premier dans le tag
Les expressions rationnelles fiables pour HTML sont difficiles . Voici comment faire avec DOM :
$dom = new DOMDocument;
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
}
Ce qui précède recherche et affiche le "outerHTML" de tous les éléments A
de la chaîne $html
.
Pour obtenir toutes les valeurs de texte du noeud, vous faites
echo $node->nodeValue;
Pour vérifier si l'attribut href
existe, vous pouvez le faire
echo $node->hasAttribute( 'href' );
Pour obtenir l'attribut href
que vous feriez
echo $node->getAttribute( 'href' );
Pour changer l'attribut href
que vous feriez
$node->setAttribute('href', 'something else');
Pour supprimer l'attribut href
que vous feriez
$node->removeAttribute('href');
Vous pouvez également interroger directement l'attribut href
avec XPath
$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//a/@href');
foreach($nodes as $href) {
echo $href->nodeValue; // echo current attribute value
$href->nodeValue = 'new value'; // set new attribute value
$href->parentNode->removeAttribute('href'); // remove attribute
}
Regarde aussi:
Sur une note de bas de page: Je suis sûr que c'est un doublon et que vous pouvez trouvez la réponse quelque part ici
Je suis d'accord avec Gordon, vous DEVEZ utiliser un analyseur HTML pour analyser le code HTML. Mais si vous voulez vraiment une regex, vous pouvez essayer celui-ci:
/^<a.*?href=(["\'])(.*?)\1.*$/
Cela correspond à <a
au début de la chaîne, suivi d'un nombre quelconque de caractères (non-gloutons) .*?
, puis href=
, suivis du lien entouré de "
ou '
.
$str = '<a title="this" href="that">what?</a>';
preg_match('/^<a.*?href=(["\'])(.*?)\1.*$/', $str, $m);
var_dump($m);
Sortie:
array(3) {
[0]=>
string(37) "<a title="this" href="that">what?</a>"
[1]=>
string(1) """
[2]=>
string(4) "that"
}
Le modèle que vous souhaitez rechercher serait le modèle d'ancrage de lien, comme (quelque chose):
$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
pourquoi ne pas juste correspondre
"<a.*?href\s*=\s*['"](.*?)['"]"
<?php
$str = '<a title="this" href="that">what?</a>';
$res = array();
preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res);
var_dump($res);
?>
puis
$ php test.php
array(2) {
[0]=>
array(1) {
[0]=>
string(27) "<a title="this" href="that""
}
[1]=>
array(1) {
[0]=>
string(4) "that"
}
}
qui fonctionne. Je viens de retirer les premières accolades de capture.
Pour ceux qui n'obtiennent toujours pas les solutions très facilement et rapidement avec SimpleXML
$a = new SimpleXMLElement('<a href="www.something.com">Click here</a>');
echo $a['href']; // will echo www.something.com
Ça marche pour moi
Je ne suis pas sûr de ce que vous essayez de faire ici, mais si vous essayez de valider le lien, regardez PHP filter_var ()
Si vous avez vraiment besoin d’utiliser une expression régulière, utilisez cet outil, il pourra vous aider: http://regex.larsolavtorvik.com/
En utilisant votre regex, je l'ai un peu modifié pour répondre à vos besoins.
<a.*?href=("|')(.*?)("|').*?>(.*)<\/a>
Je suggère personnellement que vous utilisiez un HTML Parser
EDIT: Testé
Test rapide: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>
semble faire l'affaire, le premier match étant "ou", le second la valeur "href" "et" le troisième "quoi?".
La raison pour laquelle j'ai laissé le premier match de "/ 'ici est que vous pouvez l'utiliser pour le référencer ultérieurement pour le" /' de clôture.
Voir des exemples en direct sur: http://www.rubular.com/r/jsKyK2b6do
preg_match_all ("/ (]>) (. ?) (</ a) /", $ contenu, $ impmatches, PREG_SET_ORDER);
Il est testé et récupère toutes les balises à partir de n'importe quel code HTML.
Ce qui suit fonctionne pour moi et renvoie à la fois href
et value
de la balise d'ancrage.
preg_match_all("'\<a.*?href=\"(.*?)\".*?\>(.*?)\<\/a\>'si", $html, $match);
if($match) {
foreach($match[0] as $k => $e) {
$urls[] = array(
'anchor' => $e,
'href' => $match[1][$k],
'value' => $match[2][$k]
);
}
}
Le tableau multidimensionnel appelé $urls
contient désormais des sous-tableaux associatifs faciles à utiliser.