Tengo una aplicación nodejs, que usa cheerio para extraer partes de html de páginas de varios sitios. La aplicación se ejecuta a través de un archivo JSON y realiza el raspado y la extracción para cada sitio, para todas las URL y todas las consultas de cheerio.js para cada URL:
"site1":{ "urls":{ "http://site1.com/pageA", "http://site1.com/pageB", }, "queries":{ "h1": "$('h1').text()" "numbersFromH1": "$('h1').text().match(/\\d+/)[0]" } } Cargar los selectores, por ejemplo, 'h1' usando una variable y tener un método .text() dentro de la aplicación sería una obviedad. Sin embargo, a veces necesito .match() o . filter() etc., a veces encadenan los métodos.
Entonces, ¿hay alguna forma de cargar toda la consulta (selector+métodos) y hacer que Cheerio la ejecute?
Las consultas deben ser funciones que toman $ como parámetro, porque $ es dinámico (se genera de nuevo para cada nuevo documento que analiza). Luego use ese $ que ahora está dentro del alcance dentro de la función para llamar lo que quiera, sin necesidad de eval. Por ejemplo:
const sites = { "site1":{ "urls":[ // make sure this is an array, not an object "http://site1.com/pageA", "http://site1.com/pageB", ], "queries":{ "h1": $ => $('h1').text(), // make sure to include comma after value "numbersFromH1": $ => $('h1').text().match(/\\d+/)[0] } } }; const { site1 } = sites; // replace with whatever implementation you have that retrieves page text const pageText = await getPageText(site1.urls[0]); const firstUrl$ = cheerio.load(pageText); console.log(site1.queries.h1(firstUrl$));Que debería ser fácilmente adaptable a bucles y llamadas más dinámicas de las URL y métodos.
Para responder a mi propia pregunta de inmediato: como revisión, uso eval() para analizar la consulta importada y consumir su salida.
Sin embargo, dado que eval generalmente no se recomienda y tengo dudas sobre su rendimiento, sigo buscando una solución diferente. Por ejemplo, pasando toda la cadena de consulta (no solo el selector) a cheerio, de alguna manera...