2010-09-29 23 views
106

Intentando encontrar los enlaces en una página.Asir el atributo href de un elemento A

mi expresión regular es:

/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/ 

pero parece fallar en

<a title="this" href="that">what?</a> 

¿Cómo iba a cambiar mi expresión regular para hacer frente a href no se coloca por primera vez en la etiqueta?

Respuesta

193

Reliable Regex for HTML are difficult. Aquí es cómo hacerlo con DOM:

$dom = new DOMDocument; 
$dom->loadHTML($html); 
foreach ($dom->getElementsByTagName('a') as $node) { 
    echo $dom->saveHtml($node), PHP_EOL; 
} 

Lo anterior podría encontrar la salida y la de todos los "outerHTML"A elementos en la cadena $html.

Para obtener todos los valores de texto del nodo, lo hace

echo $node->nodeValue; 

Para cheque si existe el atributo href que puede hacer

echo $node->hasAttribute('href'); 

Para obtener la href atributo que harías

echo $node->getAttribute('href'); 

Para cambio la href atributo que haría

$node->setAttribute('href', 'something else'); 

Para eliminar la href atributo que haría

$node->removeAttribute('href'); 

También puede consultar para el atributo href directamente con 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 
} 

Véase también:

En una nota: estoy seguro de que esto es un duplicado y se puede find the answer somewhere in here

+0

La expresión regular fiable para analizar HTML es intrínsecamente imposible incluso si HTML no es un lenguaje normal. – Asciiom

3

¿por qué no acaba de coincidir

"<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); 

?> 

continuación

$ php test.php 
array(2) { 
    [0]=> 
    array(1) { 
    [0]=> 
    string(27) "<a title="this" href="that"" 
    } 
    [1]=> 
    array(1) { 
    [0]=> 
    string(4) "that" 
    } 
} 

que trabaja. Acabo de quitar los primeros soportes de captura.

+2

Recomiendo usar 'preg_match_all ("/ $ val) {echo $ val [1]} ' –

+0

@IgnacioBustos funcionó bien – mostafaznv

5

El patrón que desea buscar sería el patrón de vínculo de anclaje, al igual que (algo):

$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/"; 
+1

¿Qué pasa si el ancla tiene más atributos? – funerr

1

prueba rápida: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a> parece hacer el truco, con el 1er partido ser "o', el segundo el 'href' valor 'que', y el tercero el 'qué?'.

El motivo por el que dejé la primera coincidencia de "/ 'es que puede usarlo para hacer una referencia posterior más adelante para el cierre"/'entonces es lo mismo.

Vea el ejemplo en vivo en: http://www.rubular.com/r/jsKyK2b6do

+0

no funciona, lo siento – bergin

+1

@bergin por favor especifique, ¿qué no funciona? Obtengo el valor exacto del href en tu prueba HTML. ¿Qué esperas que esto no funcione? Veo que usa un sitio diferente para probar, también obtengo el valor 'href' de su ejemplo. http://www.myregextester.com/?r=d966dd6b – CharlesLeaf

2

no estoy seguro de lo que estás tratando de hacer aquí, pero si usted está tratando de validar el enlace a continuación, un vistazo a filter_var() de PHP

Si realmente necesita usar una expresión regular entonces echa un vistazo a esta herramienta, puede ayudar: http://regex.larsolavtorvik.com/

2

Usando su expresión regular, la modifiqué un poco para adaptarla a sus necesidades.

<a.*?href=("|')(.*?)("|').*?>(.*)<\/a>

yo personalmente recomiendo que utilice un EDITAR HTML Parser

: Probado

+0

usando myregextester.com - lo siento, no encuentra los enlaces – bergin

+0

@bergin, Hola, he modificado mi respuesta, y funciona ahora. – Ruel

+0

dice: SIN PARTIDOS. COMPRUEBE COLISIÓN DELIMITER. – bergin

16

estoy de acuerdo con Gordon, DEBES usar un analizador HTML para analizar HTML. Pero si realmente quieres una expresión regular se puede probar esto:

/^<a.*?href=(["\'])(.*?)\1.*$/ 

Esto coincide con <a en el comienzo de la cadena, seguido de cualquier número de cualquier char (no codiciosos) .*? continuación href= seguido por el enlace rodeada ya sea " o '

$str = '<a title="this" href="that">what?</a>'; 
preg_match('/^<a.*?href=(["\'])(.*?)\1.*$/', $str, $m); 
var_dump($m); 

de salida:

array(3) { 
    [0]=> 
    string(37) "<a title="this" href="that">what?</a>" 
    [1]=> 
    string(1) """ 
    [2]=> 
    string(4) "that" 
} 
+0

solo por información: si buscamos en un texto que contenga muchos elementos, la expresión (. *?) Es incorrecta –

0

preg_match_all ("/ (] >) (. ?) (</a) /", $ contenido, impmatches $, PREG_SET_ORDER);

Se prueba y obtener todos una etiqueta de cualquier código html

2

Para el que aún no recibe el. soluciones muy fáciles y utilizando rápida SimpleXML

$a = new SimpleXMLElement('<a href="www.something.com">Click here</a>'); 
echo $a['href']; // will echo www.something.com 

Su trabajo para mí

Cuestiones relacionadas