1
votes

Comment attraper des liens avec des espaces optionnels en PHP?

À partir d'un file_get_contents , j'obtiens le code HTML d'une URL.

preg_match_all('/class=\"four-column mosaicElement\"><a href=\"(.+?)\" title=\"(.+?)"/m', $html, $urls, PREG_SET_ORDER, 0);

foreach ($urls as $key => $url) {
    echo $url[1];
}

Maintenant, je voudrais capturer le lien href .

Le code HTML est:

<li class="four-column mosaicElement">
<a href="https://example.com" title="Lorem ipsum">
...
</a>
</li>
<li class="four-column mosaicElement">
<a href="https://example.org" title="Lorem ipsum">
...
</a>
</li>

J'utilise donc ceci:

$html = file_get_contents($url);

Comment puis-je résoudre ce problème?


1 commentaires

Je pense que vous devriez ajouter une nouvelle ligne \ n ou \ R après class = \ "quatre colonnes mosaicElement \"> \ R . regex101.com/r/GtBZfG/1 Pourquoi ne pas utiliser DOMDocument à la place?


3 Réponses :


3
votes

J'ai pu faire fonctionner votre code en modifiant simplement le modèle de regex comme suit:

https://example.com
https://example.org

Notez attentivement que j'autorise toute quantité d'espace entre la classe code> de la balise externe (

  • ) et de l'ancre interne.

    Voici votre script mis à jour:

    $html = "<li class=\"four-column mosaicElement\">\n<a href=\"https://example.com\" title=\"Lorem ipsum\">\n</a>\n</li>\n<li class=\"four-column mosaicElement\">\n<a href=\"https://example.org\" title=\"Lorem ipsum\">\n</a>\n</li>";
    preg_match_all('/class="four-column mosaicElement">\s*<a href="(.+?)" title="(.+?)"/m', $html, $urls, PREG_SET_ORDER, 0);
    
    foreach ($urls as $key => $url) {
        echo $url[1] . "\n";
    }    
    

    Ceci imprime:

    class="four-column mosaicElement">\s*<a href="(.+?)" title="(.+?)"
                                     ^^^^^
    


    0 commentaires

    3
    votes

    Une autre option consiste à utiliser DOMXPath avec une expression xpath qui trouve tous les éléments de la liste avec les deux noms de classe, puis obtient les ancres:

    https://example.com
    https://example.org
    

    Par exemple:

    $string = <<<DATA
    <li class="four-column mosaicElement">
    <a href="https://example.com" title="Lorem ipsum">
    </a>
    </li>
    <li class="four-column mosaicElement">
    <a href="https://example.org" title="Lorem ipsum">
    </a>
    </li>
    DATA;
    
    $dom = new DOMDocument();
    $dom->loadHTML($string);
    $xpath = new DOMXpath($dom);
    
    foreach($xpath->query("//li[contains(@class, 'four-column') and contains(@class, 'mosaicElement')]/a") as $v) {
        echo $v->getAttribute("href") . PHP_EOL;
    }
    

    Résultat

    //li[contains(@class, 'four-column') and contains(@class, 'mosaicElement')]/a
    

    Voir une démo php


    0 commentaires

    1
    votes

    Ici, nous pouvons également utiliser une expression avec une anticipation positive et des espaces optionnels, juste au cas où

    https://example.com
    https://example.org
    https://example.org
    https://example.org
    

    et les URL souhaitées sont dans ce groupe:

    $re = '/(?=class="four-column mosaicElement")[\s\S]*?href="\s*(https?[^\s]+)\s*"/m';
    $str = '<li class="four-column mosaicElement">
    <a href="https://example.com" title="Lorem ipsum">
    ...
    </a>
    </li>
    <li class="four-column mosaicElement">
    <a href="https://example.org" title="Lorem ipsum">
    
    <li class="four-column mosaicElement">
    <a href="   https://example.org   " title="Lorem ipsum">
    
    <li class="four-column mosaicElement">
    <a href="   https://example.org                " title="Lorem ipsum">
    ...
    </a>
    </li>
    ';
    
    preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
    
    foreach ($matches as $key => $url) {
        echo $url[1] . "\n";
    }
    

    DEMO

    TEST h3 >
    (https?[^\s]+)
    

    Sortie

    (?=class="four-column mosaicElement")[\s\S]*?href="\s*(https?[^\s]+)\s*"
    

    Circuit RegEx

    jex.im visualise les expressions régulières:

    entrer l'image description ici


    0 commentaires