Кукловод очищает таблицы без отдельных классов

#javascript #puppeteer

#javascript #кукловод

Вопрос:

Хотя я и не новичок, у меня возникают трудности с чистой очисткой таблиц, в которых нет целевых классов / идентификаторов. Кроме того, данные находятся в странных местах, а иногда даже существуют.

Это мой текущий проект: http://a810-bisweb.nyc.gov/bisweb/OverviewForComplaintServlet?complaintno=3732304

Мне нужны следующие данные: введите описание изображения здесь

и мне нужно вывести его в виде массива пар ключ / значение.

Просто используя консоль браузеров:

 let tables = document.querySelectorAll('table') // get all tables
tables.forEach(table => document.querySelectorAll('tr').forEach(tr => console.log(tr.innerText)))

 

Я получаю этот уродливый текст, который мне нужно проанализировать, и есть так много переменных, чтобы учесть, что файл превращается в монстра из 500 строк.

Есть идеи о лучшем способе сделать это?

введите описание изображения здесь

РЕДАКТИРОВАТЬ: Дополнительный вопрос, который особенно сложно разобрать. Как вы получаете здесь только первое число? Разделение по split('amp;bnsp;') работает не слишком хорошо. введите описание изображения здесь

Ответ №1:

Вероятно, вы можете начать с первой попытки индивидуальной печати каждой ячейки. Это даст вам гораздо лучшее представление о структуре.

 let tableNum = 0;
let rowNum = 0;
const tables = document.querySelectorAll('table');
tables.forEach(table => {
    console.log(`Table: ${tableNum  }`);
    const rows = table.querySelectorAll('tr');
    rows.forEach(row => {
        console.log(`Row: ${rowNum  }`);
        const cells = row.querySelectorAll('td');
        cells.forEach(cell => console.log(cell.innerText));
    });
    rowNum = 0;
});
 

Кроме того, если class и id отсутствуют в таблицах, вы можете попытаться настроить таргетинг на любой другой атрибут, который может помочь вам более конкретно настроить таргетинг на элементы.

Комментарии:

1. Я опубликовал свою рабочую версию. Хотя я не фанат этого. Указатели?

2. Если он работает так, как ожидалось, вы должны принять его. На самом деле нет смысла пытаться оптимизировать код, чтобы он «выглядел лучше», когда он работает, если только его нельзя заставить работать быстрее. Кроме того, быстрая работа не является ключевым требованием для всех случаев. Одним из небольших изменений может быть кэширование tr.innerText переменной перед операторами if, поскольку вы вызываете tr.innerText , но здесь это просто придирки.

Ответ №2:

Это то, что я в итоге создал, но я не поклонник операторов if. У кого-нибудь еще есть идеи получше?

 const puppeteer = require("puppeteer");

module.exports = async function crawler(url) {
  const browser = await puppeteer.launch({
    args: ["--no-sandbox"],
    ignoreDefaultArgs: ["--disable-extensions"],
  });

  const page = await browser.newPage();
  await page.setDefaultNavigationTimeout(0);
  await page.goto(url);

  let results = [];

  const data = await page.evaluate(() => {
    let results = [];
    Array(document.querySelectorAll("table")).map((tables) => {
      tables.forEach((table) => {
        table.querySelectorAll("tr").forEach((tr) => {
          if (tr.innerText.includes("Overview")) {
            results.push({ status: tr.innerText.split("=")[1].trim() });
          }
          if (tr.innerText.includes("Category Code")) {
            results.push({
              "Category Code": tr.innerText
                .split("t")[1]
                .split("")
                .splice(0, 2)
                .join(""),
            });
          }
          if (tr.innerText.includes("Assigned To:")) {
            results.push({ "Assigned To": tr.innerText.split("t")[1].trim() });
            results.push({
              Priority: tr.innerText.split("t")[2].split(":")[1].trim(),
            });
          }
          if (tr.innerText.includes("Received:")) {
            results.push({ Received: tr.innerText.split("t")[1].trim() });
          }
          if (tr.innerText.includes("Owner:")) {
            results.push({ owner: tr.innerText.split("t")[1].trim() });
          }
          if (tr.innerText.includes("Last Inspection:")) {
            results.push({
              "Last Inspection": tr.innerText.split("t")[1].trim(),
            });
          }
          if (tr.innerText.includes("Disposition:")) {
            results.push({
              Disposition: tr.innerText.split("t")[1].trim(),
            });
          }
          if (tr.innerText.includes("Comments:")) {
            results.push({
              comments: tr.innerText.split("t")[1].trim(),
            });
          }
        });
      });
    });
    return results;
  });

  data.forEach((item) => results.push(item));

  const inlineForm = await page.evaluate(() => {
    let results = [];
    Array(document.querySelectorAll(".inlineform")).map((tr) => {
      tr.forEach((r) => {
        results.push({ Number: r.innerText.split("t")[0].trim() });
        results.push({ Date: r.innerText.split("t")[1].trim() });
        results.push({ Code: r.innerText.split("t")[2].trim() });
        results.push({ Disposition: r.innerText.split("t")[3].trim() });
        results.push({ "Inspection By": r.innerText.split("t")[4].trim() });
        results.push({ Date: r.innerText.split("t")[5].trim() });
      });
    });
    return results;
  });

  inlineForm.forEach((item) => results.push(item));

  await browser.close();
  return results;
};