Documentation Index

Fetch the complete documentation index at: https://supporthub.usheru.com/llms.txt

Use this file to discover all available pages before exploring further.

How to scrape Lead information from Cinando

Prev Next

1.- Create a PEOPLE LIST with the people you are interested in extracting information for

2.- Go to the list, select 40 results per page

3.- Right-click → Inspect. Go to Console and paste this script there:

function splitNameByCaps(fullName) {
  const tokens = (fullName || "").trim().split(/\s+/).filter(Boolean);

  const isAllCaps = (t) => {
    // has at least one letter (supports accents), and is uppercase
    const hasLetters = /[A-Za-zÁÉÍÓÚÜÑÇÀÈÌÒÙÂÊÎÔÛÄËÏÖÜáéíóúüñçàèìòùâêîôûäëïöü]/.test(t);
    return hasLetters && t === t.toUpperCase() && t !== t.toLowerCase();
  };

  const surnameTokens = [];
  const firstNameTokens = [];

  for (const t of tokens) {
    if (isAllCaps(t)) surnameTokens.push(t);
    else firstNameTokens.push(t);
  }

  return {
    firstNames: firstNameTokens.join(" "),
    surnames: surnameTokens.join(" ")
  };
}


function extractPeopleFromCurrentPage() {
  const items = Array.from(document.querySelectorAll("div.item"));

  return items.map(item => {
    const getText = (sel) =>
      item.querySelector(sel)?.textContent.trim() || "";

    const fullName = getText(".item--author--name a");
    const { firstNames, surnames } = splitNameByCaps(fullName);

    const functionName = getText(".item--author--function");
    const title = getText(".item--author--title");

    const phones = Array.from(
      item.querySelectorAll(".item--author--phones .mobile, .item--author--phones .phone")
    )
      .map(el => el.textContent.trim())
      .filter(Boolean)
      .join(" | ");

    const mailto = item.querySelector(
      ".item--author--links .mail a[href^='mailto:']"
    )?.getAttribute("href") || "";

    const email = mailto
      ? mailto.replace(/^mailto:/i, "").split("?")[0].trim()
      : "";

    const companyName = getText(".item--company--name a");
    const companyCountry = getText(".item--company--country");
    const companyCopyright = (
      item.querySelector(".item--company--copyright")?.innerText || ""
    ).replace(/\s+\n/g, "\n").trim();

    return {
      firstNames,
      surnames,
      fullName,
      function: functionName,
      title,
      phones,
      email,
      companyName,
      companyCountry,
      companyCopyright
    };
  });
}

async function scrapeAllPagesUntilEnd({
  pauseMs = 700,          // extra wait after page changes
  maxWaitMs = 12000       // max time to wait for DOM change after clicking next
} = {}) {
  const all = [];
  let page = 1;

  const nextBtn = () => document.querySelector(".pagi .next");

  const getItems = () => Array.from(document.querySelectorAll("div.item"));

  const pageSignature = () =>
    getItems()
      .map(el => el.querySelector(".item--author--name a")?.textContent.trim())
      .filter(Boolean)
      .join("||");

  const isNextDisabled = (btn) => {
    if (!btn) return true;
    const cls = btn.className || "";
    return (
      cls.includes("disabled") ||
      cls.includes("inactive") ||
      btn.getAttribute("aria-disabled") === "true"
    );
  };

  while (true) {
    const items = getItems();
    if (items.length === 0) {
      console.log("No items found — stopping.");
      break;
    }

    console.log(`Scraping page ${page}... (${items.length} items)`);
    all.push(...extractPeopleFromCurrentPage());

    const btn = nextBtn();
    if (!btn || isNextDisabled(btn)) {
      console.log("Next page not available — stopping.");
      break;
    }

    const before = pageSignature();
    btn.click();

    // Wait for signature to change
    const start = Date.now();
    while (Date.now() - start < maxWaitMs) {
      await new Promise(r => setTimeout(r, 200));
      const after = pageSignature();
      if (after && after !== before) break;
    }

    // small extra pause for lazy rendering
    await new Promise(r => setTimeout(r, pauseMs));

    const afterFinal = pageSignature();
    if (!afterFinal || afterFinal === before) {
      console.log("Page did not change after clicking next — stopping.");
      break;
    }

    page++;
  }

  console.log("Done. Total records:", all.length);
  return all;
}

// Run it:
scrapeAllPagesUntilEnd().then(data => {
  window.__peopleScrape = data;
  console.table(data.slice(0, 5));
});

4.- Let the script run through all available pages in your list. Once completed, execute this script to download the data:

function downloadCSV(data, filename = "people.csv") {
  if (!data?.length) return console.warn("No data to download.");

  const headers = Object.keys(data[0]);
  const escape = (v) => `"${String(v ?? "").replace(/"/g, '""')}"`;

  const rows = [
    headers.join(","),
    ...data.map(row => headers.map(h => escape(row[h])).join(","))
  ];

  const blob = new Blob([rows.join("\n")], { type: "text/csv;charset=utf-8;" });
  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

downloadCSV(window.__peopleScrape, "people_all_pages.csv");

A CSV file will be automatically downloaded.