diff --git a/background.js b/background.js new file mode 100644 index 0000000..16cf195 --- /dev/null +++ b/background.js @@ -0,0 +1,82 @@ +console.log("background run"); +let jobs = {}; + +// Establece una conexion para escuchar los comandos entrantes +chrome.runtime.onConnect.addListener(function (port) { + port.onMessage.addListener(async function (params, sender) { + const [tab] = await chrome.tabs.query({ + active: true, + currentWindow: true, + }); + + //no encontro la tab + if (!tab) { + console.log("error al conseguir la tab"); + return; + } + console.log("tab found"); + + //establece un puerto con el content script + let portContentScript = chrome.tabs.connect(tab.id, { + name: "bg-content_script", + }); + + // si el comando que llega es "start" ... (desde indexjs) + if (params.cmd === "start") { + //envia el comando 'scrap' al contentscript + console.log("envia scrap a contetn"); + portContentScript.postMessage({ cmd: "scrap" }); + } + + // si el comando que esta recibiendo es stop (indexjs) + if (params.cmd === "stop") { + //envia el comando stop al contentscript + portContentScript.postMessage({ cmd: "stop" }); + } + + // si el comando que recibe es saveInfo (contentscript) + if (params.cmd === "saveInfo") { + // guarda la info entrante en la variable global jobs + const { jobsInfo } = params; + + //acomoda el nuevo conjunto de jobsInformation a lo que ya se tiene ? + jobsInfo.forEach((job) => { + const { location, salary } = job; + + // si no existe esa localidad en jobs + if (!jobs[location]) { + //crea la localidad y le asigna un nuevo arreglo con el salario y la cantidad 1 + jobs[location] = [{ salary, count: 1 }]; + } else { + //ya existe esa localidad + let bool = false; + + jobs[location].forEach((u) => { + //si ese salario ya existe + if (u.salary == salary) { + bool = true; + u.count++; //aumenta el contador + } + }); + + //en caso no existia ese salario + if (!bool) { + //pushea el nuevo salario con count en 1 + jobs[location].push({ salary, count: 1 }); + } + } + }); + } + + // si el comando que recbie es saveInLocalStorage ((contentscript)) + if (params.cmd === "saveInLocalStorage") { + //guarda jobs en el localStorage + chrome.storage.local.set({ + jobsAnalysis: JSON.stringify({ data: jobs }), + }); + + //resetea la variable donde estaba guardando los trabajos + jobs = {}; + } + }); +}); diff --git a/contentscript.js b/contentscript.js new file mode 100644 index 0000000..e574af4 --- /dev/null +++ b/contentscript.js @@ -0,0 +1,85 @@ +// nos devuelve un array de objetos con la info importante de cada aviso +function jobCardsInfo() { + //obtiene todos los elementos cuyos id comienzan con "jobcard" + // los recibe como nodos y con el spread operator convertimos el array de Nodes a un array de Elements + const jobCards = [...document.querySelectorAll("div[id*=jobcard]")]; + + // extraemos solo la informacion que queremos + return jobCards.map((card) => { + // Del cardJob extraemos: fecha, titulo del trabajo, salario + const [{ innerText: date }, { innerText: title }, { innerText: salary }] = + card.children[1].children[0].children; // card.children me da 2 elementos, pero la info esta en el 2do. Y de ese 2do elemento necesito su primer hijo. Y finalmente los hijos de este ultimo + + // Del cardJob extramos: localidad + const locations = [...card.querySelectorAll("a[title*=Empleos]")]; + // locations me devuelve un array de 2 elementos. La localidad y el estado + // pero hay cards que no tienen localidad, solamente estado + + // por ello pongo el reverse()[0] + let [{ title: location } = { title: "" }] = + locations.reverse(); + + // si el card no tiene location le asignamos "" y luego al imprimir en el front le pondremos "Sin especificar localidad" + if (location === "") { + return { title, salary, location }; + } + //location = location.slice(11); // le quitamos el "empleos en " + return { title, salary, location: location.slice(11) }; + }); +} + +// establece una conexion con el background +//const buttonNext = () => document.querySelector("li[class*=next]"); // +const element = document.querySelector("div[class*=jobCardContainer]"); +const portBackground = chrome.runtime.connect({ + name: "content_script-background", +}); + +let mutation = null; +chrome.runtime.onConnect.addListener(function (port) { + port.onMessage.addListener(({ cmd }) => { + if (cmd === "scrap") { + console.log("scrapeando"); + mutation = new MutationObserver(() => { + const buttonNext = document.querySelector("li[class*=next]"); + console.log("buttonNext", buttonNext); + if (buttonNext) { + console.log("existe el button next "); + const nextPage = buttonNext.className.includes("disabled"); + + //si es que no tiene la clase disabled + if (nextPage === false) { + const jobsInfo = jobCardsInfo(); + + //envia la info al background para que la vaya sumando + portBackground.postMessage({ + cmd: "saveInfo", + jobsInfo, + }); + buttonNext.click(); + } else { + mutation && mutation.disconnect(); + portBackground.postMessage({ cmd: "saveInLocalStorage" }); + } + } + //alertar que no hubo boton (por implementar) + }); + + mutation.observe(element, { subtree: true, childList: true }); + + const jobsInfo = jobCardsInfo(); + + portBackground.postMessage({ + cmd: "saveInfo", + jobsInfo, + }); + + document.querySelector("li[class*=next]").click(); + } + + if (cmd === "stop") { + mutation && mutation.disconnect(); + portBackground.postMessage({ cmd: "saveInLocalStorage" }); + } + }); +}); diff --git a/images/occ.png b/images/occ.png new file mode 100644 index 0000000..f5ae218 Binary files /dev/null and b/images/occ.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..4ed731a --- /dev/null +++ b/manifest.json @@ -0,0 +1,23 @@ +{ + "manifest_version": 3, + "name": "jobs-scraping", + "author": "https://github.com/GersoZz", + "version": "1.0.0", + "description": "Scraping Jobs Offers", + "permissions": ["tabs", "storage", "activeTab", "scripting"], + "background": { + "service_worker": "./background.js" + }, + "action": { + "default_popup": "./popup/index.html" + }, + "icons": { + "32": "./images/occ.png" + }, + "content_scripts": [ + { + "matches": ["https://www.occ.com.mx/*"], + "js": ["./contentscript.js"] + } + ] +} diff --git a/popup/index.html b/popup/index.html new file mode 100644 index 0000000..efbb9c9 --- /dev/null +++ b/popup/index.html @@ -0,0 +1,45 @@ + + +
+ + + + + + + + +