Arcane.Html
Ler HTML de verdade: seletor CSS, tabela como dado, e as duas defesas contra XSS.
Ler uma página — um preço, uma tabela, os links — só dava por expressão regular, e HTML não é regular. A marcação que funciona no teste quebra no primeiro atributo fora de ordem, na primeira tag sem fechar, no primeiro <br> no meio.
Seletor CSS#
adopt Arcane.Html as Html
doc := Html.ler(pagina)
out doc.achar("#p1 h2").texto
out [n.texto cycle n in doc.achar_todos("div.produto > h2")]
out doc.achar("a[href]").atributo("href")| Escrita | Casa |
|---|---|
div | a tag |
.classe | quem tem a classe |
#id | quem tem o id |
[attr] · [attr=valor] | por atributo |
a b | b em qualquer lugar dentro de a |
a > b | b filho direto de a |
É CSS, e não XPath: div.preco > span é o que quem escreve HTML já sabe de cor.
O texto junta com espaço#
<span class="preco"><b>R$</b> <span>450,00</span></span>out doc.achar(".preco").texto // "R$ 450,00"Colado, isso viraria R$450,00. Com espaço é o que a página mostra — e é o que quem extrai quer.
Extrair#
out doc.links("https://forja.br/loja/")
// [{texto: Ver, destino: https://forja.br/produto/1, titulo: }]
out doc.tabela()
// {cabecalho: [Item, Preço], linhas: [[Bigorna, 450], [Marreta, 75]]}
out doc.imagens()As duas defesas#
Escapar — antes de mostrar#
respond html $"<p>{Html.escapar(comentario)}</p>"É a defesa contra XSS que mais se esquece: um texto que veio de fora, escrito direto na página, é código.
Limpar — tirar toda a marcação#
assert Html.limpar("<p>ok</p><script>roubar()</script>") is "ok"Podar — deixar alguma marcação#
Para comentário e conteúdo de usuário, onde negrito e link fazem sentido:
seguro := Html.podar(comentario)
// <p>, <b>, <a>, <ul>… passam; <script>, <iframe>, <style> somemHTML real não é bem formado#
Tag sem fechar, tag fechada que ninguém abriu, <br> solto: o leitor engole tudo isso, porque a página que você quer ler está cheia disso e derrubar a leitura não serve a ninguém.