Pitch: Fiz um Parser de HTML em Rust para Node.js
Uns tempos atrás quando procurava bibliotecas para a manipuação de imagens em Node.js, conheci o @napi-rs/canvas que é uma biblioteca escrita em Rust; fiquei curioso sobre e vi que NAPI-RS é um framework que faz essa ponte entre Rust e Node.js, permitindo que você crie bibliotecas rápidas em Rust e as use no Node.js até com tipagens prontas.
Ontem, querendo fazer um teste, para ver se eu conseguiria criar a biblioteca mais rápida de parsing de HTML no ecossistema do Node.js, iniciei o Xcrap HTML Parser e, eu consegui:
Comparação com as outras bibliotecas do ecossitema Node.js:
@xcrap/html-parser :0.246214 ms/file ± 0.136808
html-parser :36.8255 ms/file ± 28.8551
htmljs-parser :0.501577 ms/file ± 1.21080
html-dom-parser :2.18028 ms/file ± 1.79617
html5parser :1.67464 ms/file ± 1.22279
cheerio :8.67998 ms/file ± 6.32852
parse5 :4.82118 ms/file ± 2.66822
htmlparser2 :1.49739 ms/file ± 1.39804
htmlparser :16.1712 ms/file ± 109.076
high5 :2.98229 ms/file ± 1.92748
node-html-parser :2.90167 ms/file ± 1.90804
Claro que eu não fiz tudo do zero, na verdade, foi pouca coisa até. Utilizei essas bibliotecas já existentes no ecossistema do Rust:
Instalação
A instalação é muito simples, você pode usar o NPM ou qualquer outro gerenciador de pacotes de sua escolha: como PNPM, Yarn, etc.
npm i @xcrap/html-parser
Como Usar
import { HtmlParser, css, xpath } from "@xcrap/html-parser"
// HTML de exemplo
const html = `
<div>
<h1 class="title">Hello World</h1>
<p>Web scraping com Rust é rápido!</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
`
// Instanciamos o parser
const parser = new HtmlParser(html)
// Selecionando um elemento
const heading1 = parser.selectFirst({ query: xpath("//h1") })
console.log(heading1.text)
// Selecionando vários elementos
const listItems = parser.selectMany({ query: css("ul li"), limit: 2 })
const texts = listItems.map(item => item.text)
console.log(texts)
Se tiverem interesse em contribuirem/ajudarem na documentação, fiquem à vontade para subir um PR ;)