Pergunta

Eu tenho um parágrafo de texto em uma variável javascript chamado 'input_content' e que o texto contém várias marcas de âncora / links. Eu gostaria de combinar todas as marcas de âncora e extrato de texto âncora e URL, e colocá-lo em uma matriz como (ou similar) este:

Array
(
    [0] => Array
        (
            [0] => <a href="http://yahoo.com">Yahoo</a>
            [1] => http://yahoo.com
            [2] => Yahoo
        )
    [1] => Array
        (
            [0] => <a href="http://google.com">Google</a>
            [1] => http://google.com
            [2] => Google
        )
)

Eu tomei um crack para ele ( http://pastie.org/339755 ), mas eu estou perplexo além deste ponto. Obrigado pela ajuda!

Foi útil?

Solução

var matches = [];

input_content.replace(/[^<]*(<a href="([^"]+)">([^<]+)<\/a>)/g, function () {
    matches.push(Array.prototype.slice.call(arguments, 1, 4))
});

Isso pressupõe que suas âncoras sempre estará na forma <a href="...">...</a> ou seja, não vai funcionar se existem outros atributos (por exemplo, target). A expressão regular pode ser melhorado para acomodar isso.

Para quebrar a expressão regular:

/ -> start regular expression
  [^<]* -> skip all characters until the first <
  ( -> start capturing first token
    <a href=" -> capture first bit of anchor
    ( -> start capturing second token
        [^"]+ -> capture all characters until a "
    ) -> end capturing second token
    "> -> capture more of the anchor
    ( -> start capturing third token
        [^<]+ -> capture all characters until a <
    ) -> end capturing third token
    <\/a> -> capture last bit of anchor
  ) -> end capturing first token
/g -> end regular expression, add global flag to match all anchors in string

Cada chamada para a função anónimo vai receber três sinais como a segunda, terceira e quarta argumentos, nomeadamente argumentos [1], [2] argumentos, argumentos [3]:

  • argumentos [1] é toda a âncora
  • argumentos [2] é a parte href
  • argumentos [3] é o interior texto

Vamos usar um hack para empurrar estes três argumentos como uma nova matriz para a nossa gama matches principal. O arguments variável interna não é uma verdadeira matriz JavaScript, por isso vamos ter de aplicar o método split matriz nele para extrair os itens que queremos:

Array.prototype.slice.call(arguments, 1, 4)

Isto irá extrair itens de arguments começando no índice 1 e terminando (não incluído) no índice 4.

var input_content = "blah \
    <a href=\"http://yahoo.com\">Yahoo</a> \
    blah \
    <a href=\"http://google.com\">Google</a> \
    blah";

var matches = [];

input_content.replace(/[^<]*(<a href="([^"]+)">([^<]+)<\/a>)/g, function () {
    matches.push(Array.prototype.slice.call(arguments, 1, 4));
});

alert(matches.join("\n"));

Dá:

<a href="http://yahoo.com">Yahoo</a>,http://yahoo.com,Yahoo
<a href="http://google.com">Google</a>,http://google.com,Google

Outras dicas

Uma vez que você estiver executando presumivelmente o JavaScript em um navegador web, regex parece ser uma má idéia para isso. Se o parágrafo veio da página em primeiro lugar, obter uma alça para o recipiente, chamada .getElementsByTagName() para obter as âncoras, e, em seguida, extrair os valores que você quer assim.

Se isso não for possível, então, criar um novo objeto elemento html, atribuir o seu texto a ele de propriedade .innerHTML, e depois chamar .getElementsByTagName().

Eu acho que Joel tem o direito dela - expressões regulares são notórios por jogar mal com a marcação, pois há simplesmente demasiado muitas possibilidades a considerar. Existem outros atributos para as marcas de âncora? Que ordem é que eles estão? É o espaço em branco separando sempre um único espaço? Vendo como você já tem HTML de um navegador parser disponíveis, melhor para colocar isso para o trabalho em seu lugar.

function getLinks(html) {
    var container = document.createElement("p");
    container.innerHTML = html;

    var anchors = container.getElementsByTagName("a");
    var list = [];

    for (var i = 0; i < anchors.length; i++) {
        var href = anchors[i].href;
        var text = anchors[i].textContent;

        if (text === undefined) text = anchors[i].innerText;

        list.push(['<a href="' + href + '">' + text + '</a>', href, text];
    }

    return list;
}

Isso irá retornar um array como o que você descreve, independentemente de como os links são armazenados. Note que você pode mudar a função para trabalhar com um elemento passado em vez de texto, alterando o nome do parâmetro para "container" e remover as duas primeiras linhas. A propriedade textContent / innerText obtém o texto exibido para o link, despojado de qualquer marcação (negrito / itálico / font / ...). Você poderia substituir .textContent com .innerHTML e remover a instrução interna, se () se você quiser preservar a marcação.

JQuery seria sua melhor aposta. Este não é o melhor roteiro e tenho certeza que os outros podem dar algo melhor. Mas isso cria uma matriz de exatamente o que você está procurando.

<script type="text/javascript">
    // From http://brandonaaron.net Thanks!
    jQuery.fn.outerHTML = function() {
        return $('<div>').append( this.eq(0).clone() ).html();
    };    

    var items = new Array();
    var i = 0;

    $(document).ready(function(){
        $("a").each(function(){
            items[i] = {el:$(this).outerHTML(),href:this.href,text:this.text};
            i++;      
        });
    });

    function showItems(){
        alert(items);
    }

</script>

Para extrair o url:

var pattern = /.href="(.)".*/; var url = string.replace (padrão, '$ 1');

Demonstração:

//var string = '<a id="btn" target="_blank" class="button" href="https://yourdomainame.com:4089?param=751&amp;2ndparam=2345">Buy Now</a>;'
//uncomment the above as an example of link.outerHTML

var string = link.outerHTML
var pattern = /.*href="(.*)".*/;
var href = string.replace(pattern,'$1');
alert(href)

Para "texto âncora", por que não usar: link.innerHtml

Para o benefício dos pesquisadores: Eu criei algo que irá trabalhar com atributos adicionais na tag âncora. Para aqueles não familiarizados com Regex, o dólar ($ 1 etc) os valores são os jogos de grupo regex.

var text = 'This is my <a target="_blank" href="www.google.co.uk">link</a> Text';
var urlPattern = /([^+>]*)[^<]*(<a [^>]*(href="([^>^\"]*)")[^>]*>)([^<]+)(<\/a>)/gi;
var output = text.replace(urlPattern, "$1___$2___$3___$4___$5___$6");
alert(output);

Veja a trabalhar jsFiddle e regex101 .

Como alternativa, você pode obter informações para fora dos grupos assim:

var returnText = text.replace(urlPattern, function(fullText, beforeLink, anchorContent, href, lnkUrl, linkText, endAnchor){
                    return "The bits you want e.g. linkText";
                });
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top