web-dev-qa-db-fra.com

Saisir l'attribut href d'un élément A

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

109
bergin

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

202
Gordon

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"
}
17
Toto

Le modèle que vous souhaitez rechercher serait le modèle d'ancrage de lien, comme (quelque chose):

$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
5
Alex Pliutau

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.

3
Aif

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

2
Milan Malani

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/

2
Adam

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é

2
Ruel

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

1
CharlesLeaf

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.

0
Ravi Prakash

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.

0
Meloman