JSerwatka / Filmweb2Letterboxd

Eksport ocen z Filmweb'u do pliku csv w formacie akceptowanym przez importer Letterboxd
MIT License
28 stars 0 forks source link

Skrypt nie działa #7

Closed ozz2024 closed 9 months ago

ozz2024 commented 9 months ago

Po setnym filmie wyskakuje błąd: "Uncaught (in promise) TypeError: Cannot read properties of null (reading 'href')."

JSerwatka commented 9 months ago

@ozz2024 Hej, dzięki za zgłoszenie! Mógłbyś proszę sprawdzić kilka rzeczy:

  1. Czy jesteś zalogowany?
  2. Czy próbujesz eksportować swoje oceny?
  3. Czy jesteś na stronie https://www.filmweb.pl/user/<Twój_username>#/votes/film (albo serial)?
  4. Czy zmieniałeś przełączałeś/minimalizowałeś okno filmweba po puszczeniu skryptu?
  5. Czy przed rozpoczęciem ściągania, skrypt dojeżdża do samego końca strony (wczytuje wszystkie filmy)?

Jeśli po sprawdzeniu tych rzeczy dalej nie działa, daj mi proszę info:

  1. Czy to jest dokładnie po 100 filmie (101 film)?
  2. Co to za film?
podwieczorekk commented 9 months ago

Cześć,

mam dokładnie ten sam problem, wyświetla się komunikat: VM1671:160 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'href') at getAllRates (:160:62) at async main (:215:18)

Komunikat wyświetla się po informacji, że: pobrano 100 z 1357

Próbowałem uruchomić ten skrypt kilkakrotnie, za każdym razem ten sam błąd.

A propos Twoich pytań to: 1- tak 2- tak 3 - tak 4 - nie 5 - tak

To jest dokładnie po 100 filmie (101 film) U mnie to jest "Georgie ma się dobrze".

JSerwatka commented 9 months ago

@podwieczorekk Jeszcze potrzebuję info jakiej przeglądarki używasz. Testowałem wszystko na chromie, i o ile się nie przełącza na inne karty, to wszystko działa u mnie jak należy.

podwieczorekk commented 9 months ago

Próbowałem zarówno na Chrome jak i na Mozilli, w obu przypadkach ten sam błąd.

JSerwatka commented 9 months ago

@podwieczorekk Spróbuj proszę tej wersji poniżej i jeśli się znowu wywali, podeśli mi to co jest w HTML i index: image

function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
  function scrollToBottom() {
    window.scrollTo(0, document.body.scrollHeight);
  }

  return new Promise((resolve, reject) => {
    if (!allMoviesContainer) {
      reject("Błąd skryptu: Target element not found.");
      return;
    }

    if (!expectedChildCount) {
      reject("Błąd skryptu: No children found");
      return;
    }

    const currentChildCount = allMoviesContainer.children.length;
    if (currentChildCount >= expectedChildCount) {
      resolve(allMoviesContainer.children);
    }

    const checkAndScroll = (mutationsList) => {
      for (const mutation of mutationsList) {
        if (mutation.type === "childList") {
          scrollToBottom();
          const currentChildCount = allMoviesContainer.children.length;

          if (currentChildCount >= expectedChildCount) {
            // All expected children are now visible, scrolling is done
            observer.disconnect();
            resolve(allMoviesContainer.children);
          }
        }
      }
    };

    const observer = new MutationObserver(checkAndScroll);

    observer.observe(allMoviesContainer, { childList: true, subtree: true });

    // Initialize creating new children
    scrollToBottom();
  });
}

function formatDate(dateNumber) {
  const dateStr = dateNumber.toString();

  const year = dateStr.substring(0, 4);
  const month = dateStr.substring(4, 6);
  const day = dateStr.substring(6, 8);

  return `${year}-${month}-${day}`;
}

async function getMovieData(movieUrl) {
  const parser = new DOMParser();

  const DOMContent = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania danych filmu`);
      }
      return response.text();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!DOMContent) {
    return undefined;
  }

  const htmlDocument = parser.parseFromString(DOMContent, "text/html");

  let title = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
  )?.textContent;
  if (!title) {
    title = htmlDocument.querySelector(
      ".filmCoverSection__titleDetails > .filmCoverSection__title"
    )?.textContent;
  }

  let year = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__year"
  )?.textContent;
  year = year.split(" - ")[0]; // handle serial dates
  const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;

  return {
    movieId,
    movieData: {
      Title: title.includes(",") ? `"${title}"` : title,
      Year: year,
    },
  };
}

async function getRatingData(movieId, contentType) {
  const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
  const ratingJSON = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
      }
      return response.json();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!ratingJSON) {
    return undefined;
  }

  return {
    WatchedDate: formatDate(ratingJSON.viewDate),
    ...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
  };
}

async function waitForElement(baseElement, selector, timeout = 5000) {
  let timeoutId;

  return new Promise((resolve) => {
    if (baseElement.querySelector(selector)) {
      return resolve(baseElement.querySelector(selector));
    }

    const observer = new MutationObserver((mutations) => {
      if (baseElement.querySelector(selector)) {
        timeoutId && clearTimeout(timeoutId);
        observer.disconnect();
        resolve(baseElement.querySelector(selector));
      }
    });

    observer.observe(baseElement, {
      childList: true,
      subtree: true,
    });

    timeoutId = setTimeout(() => {
      observer.disconnect();
      resolve(undefined);
    }, timeout);
  });
}

async function getAllRates() {
  const contentType = window.location.href.split("/").pop();

  const allMoviesContainer = document.querySelector(
    'div[data-group="userPage"]  section > div:nth-child(2)'
  );
  const expectedChildCount = Number(
    document.querySelector(
      'div[data-group="userPage"] li > a.active[data-counter]'
    ).dataset.counter ?? ""
  );
  let allMoviesElements;

  try {
    allMoviesElements = await loadAllInfiniteScrollChildren(
      allMoviesContainer,
      expectedChildCount
    );
  } catch (error) {
    throw new Error(error);
  }

  const allRates = [];

  for (let i = 0; i <= expectedChildCount - 1; i++) {
    const movieLinkChild = await waitForElement(
      allMoviesElements[i],
      "a > [data-btn-center-sel=poster]"
    );
    const movieLink = movieLinkChild?.parentElement?.href;

    try {
      if (!movieLink) {
        console.log("HTML: ", allMoviesElements[i]);
        console.log("index: ", i);
        throw Error("Nie znaleziono filmu");
      }

      const { movieId, movieData } = await getMovieData(movieLink);
      if (!movieId || !movieData) {
        continue;
      }
      const ratingData = await getRatingData(movieId, contentType);

      allRates.push({ ...movieData, ...ratingData });
    } catch (e) {
      console.log(e);
      return allRates;
    }
    console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
  }
  return allRates;
}

function download(filename, text) {
  const element = document.createElement("a");
  element.setAttribute(
    "href",
    "data:text/plain;charset=utf-8," + encodeURIComponent(text)
  );
  element.setAttribute("download", filename);
  element.style.display = "none";
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

function arrayToCsv(allRates) {
  let csvRates = Object.keys(allRates[0]).join(",") + "\n";
  let filesArray = [];

  for (let i = 0; i < allRates.length; i++) {
    // Split csv for rate count > 1800
    if (i % 1799 == 0 && i > 0) {
      filesArray.push(csvRates);
      csvRates = Object.keys(allRates[0]).join(",") + "\n";
    }
    csvRates += Object.values(allRates[i]).join(",");
    csvRates += "\n";
  }
  filesArray.push(csvRates);

  return filesArray;
}

async function main() {
  console.log("Rozpoczynam pobieranie, cierpliwości...");
  console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
  let allRates = await getAllRates();
  console.log("rozpoczynam ściąganie pliku csv");
  let csvRates = arrayToCsv(allRates);

  for (let i = 0; i < csvRates.length; i++) {
    download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
  }
}

main();
podwieczorekk commented 9 months ago

Tym razem również zatrzymało się na 100, ale zamiast się wywalić pojawiła się propozycja pobrania pliku csv z tymi 100 filmami (i rzeczywiście plik posiada 100 tytułów).

Co do treści, którą miałem skopiować, to tutaj:

JSerwatka commented 9 months ago

@podwieczorekk nie było nic w HTML, puste?

pgarbocz commented 9 months ago

Mam ten sam problem, po stówie się wywala

pgarbocz commented 9 months ago

@JSerwatka HTML zwraca pustego diva (z twojego zmodyfikowanego skryptu): <div class="sc-jBqsNv hPEvkm"></div>

Error: Nie znaleziono filmu at getAllRates (:198:15) at async main (:253:18)

JSerwatka commented 9 months ago

@pgarbocz dzięki za podesłanie. Wygląda na to, że zawartość filmu nie zdążyła się wczytać. Zrobię kilka modyfikacji i spróbujemy jeszcze raz, bo nie jestem w stanie tego odtworzyć u siebie

JSerwatka commented 9 months ago

@pgarbocz @podwieczorekk Sprawdźcie proszę tę wersję:

function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
  function scrollToBottom() {
    window.scrollTo(0, document.body.scrollHeight);
  }

  return new Promise((resolve, reject) => {
    if (!allMoviesContainer) {
      reject("Błąd skryptu: Target element not found.");
      return;
    }

    if (!expectedChildCount) {
      reject("Błąd skryptu: No children found");
      return;
    }

    const currentChildCount = allMoviesContainer.children.length;
    if (currentChildCount >= expectedChildCount) {
      resolve(allMoviesContainer.children);
    }

    const checkAndScroll = (mutationsList) => {
      for (const mutation of mutationsList) {
        if (mutation.type === "childList") {
          scrollToBottom();
          const currentChildCount = allMoviesContainer.children.length;

          if (currentChildCount >= expectedChildCount) {
            // All expected children are now visible, scrolling is done
            observer.disconnect();
            resolve(allMoviesContainer);
          }
        }
      }
    };

    const observer = new MutationObserver(checkAndScroll);

    observer.observe(allMoviesContainer, { childList: true, subtree: true });

    // Initialize creating new children
    scrollToBottom();
  });
}

function formatDate(dateNumber) {
  const dateStr = dateNumber.toString();

  const year = dateStr.substring(0, 4);
  const month = dateStr.substring(4, 6);
  const day = dateStr.substring(6, 8);

  return `${year}-${month}-${day}`;
}

async function getMovieData(movieUrl) {
  const parser = new DOMParser();

  const DOMContent = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania danych filmu`);
      }
      return response.text();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!DOMContent) {
    return undefined;
  }

  const htmlDocument = parser.parseFromString(DOMContent, "text/html");

  let title = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
  )?.textContent;
  if (!title) {
    title = htmlDocument.querySelector(
      ".filmCoverSection__titleDetails > .filmCoverSection__title"
    )?.textContent;
  }

  let year = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__year"
  )?.textContent;
  year = year.split(" - ")[0]; // handle serial dates
  const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;

  return {
    movieId,
    movieData: {
      Title: title.includes(",") ? `"${title}"` : title,
      Year: year,
    },
  };
}

async function getRatingData(movieId, contentType) {
  const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
  const ratingJSON = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
      }
      return response.json();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!ratingJSON) {
    return undefined;
  }

  return {
    WatchedDate: formatDate(ratingJSON.viewDate),
    ...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
  };
}

async function waitForElement(baseElement, selector, timeout = 5000) {
  let timeoutId;

  return new Promise((resolve) => {
    if (baseElement.querySelector(selector)) {
      return resolve(baseElement.querySelector(selector));
    }

    const observer = new MutationObserver((mutations) => {
      if (baseElement.querySelector(selector)) {
        timeoutId && clearTimeout(timeoutId);
        observer.disconnect();
        resolve(baseElement.querySelector(selector));
      }
    });

    observer.observe(baseElement, {
      childList: true,
      subtree: true,
    });

    timeoutId = setTimeout(() => {
      observer.disconnect();
      resolve(undefined);
    }, timeout);
  });
}

async function getAllRates() {
  const contentType = window.location.href.split("/").pop();
  const MOVIE_GRID_SECTION_SELECTOR = 'div[data-group="userPage"]  section > div:nth-child(2)'
  const allMoviesContainer = document.querySelector(MOVIE_GRID_SECTION_SELECTOR);
  const expectedChildCount = Number(
    document.querySelector(
      'div[data-group="userPage"] li > a.active[data-counter]'
    ).dataset.counter ?? ""
  );
  let allMoviesElements;

  try {
    allMoviesElements = await loadAllInfiniteScrollChildren(
      allMoviesContainer,
      expectedChildCount
    );
  } catch (error) {
    throw new Error(error);
  }

  const allRates = [];

  for (let i = 0; i <= expectedChildCount - 1; i++) {
    const next_movie_selector = `${MOVIE_GRID_SECTION_SELECTOR} > div:nth-child(${i+1}) a > [data-btn-center-sel=poster]`
    const movieLinkChild = await waitForElement(
      document,
      next_movie_selector
    );
    const movieLink = movieLinkChild?.parentElement?.href;

    try {
      if (!movieLink) {
        console.log("HTML: ", movieLinkChild?.parentElement?.parentElement);
        console.log("index: ", i);
        throw Error("Nie znaleziono filmu");
      }

      const { movieId, movieData } = await getMovieData(movieLink);
      if (!movieId || !movieData) {
        continue;
      }
      const ratingData = await getRatingData(movieId, contentType);

      allRates.push({ ...movieData, ...ratingData });
    } catch (e) {
      console.log(e);
      return allRates;
    }
    console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
  }
  return allRates;
}

function download(filename, text) {
  const element = document.createElement("a");
  element.setAttribute(
    "href",
    "data:text/plain;charset=utf-8," + encodeURIComponent(text)
  );
  element.setAttribute("download", filename);
  element.style.display = "none";
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

function arrayToCsv(allRates) {
  let csvRates = Object.keys(allRates[0]).join(",") + "\n";
  let filesArray = [];

  for (let i = 0; i < allRates.length; i++) {
    // Split csv for rate count > 1800
    if (i % 1799 == 0 && i > 0) {
      filesArray.push(csvRates);
      csvRates = Object.keys(allRates[0]).join(",") + "\n";
    }
    csvRates += Object.values(allRates[i]).join(",");
    csvRates += "\n";
  }
  filesArray.push(csvRates);

  return filesArray;
}

async function main() {
  console.log("Rozpoczynam pobieranie, cierpliwości...");
  console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
  let allRates = await getAllRates();
  console.log("rozpoczynam ściąganie pliku csv");
  let csvRates = arrayToCsv(allRates);

  for (let i = 0; i < csvRates.length; i++) {
    download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
  }
}

main();
podwieczorekk commented 9 months ago

U mnie nie działa, ponownie zatrzymuje się na 100. HTML mam oznczony jako "undefined". Treść błędu: Error: Nie znaleziono filmu at getAllRates (:197:15) at async main (:252:18)

pgarbocz commented 9 months ago

Po 100 next_movie_selector zwraca div[data-group="userPage"] section > div:nth-child(2) > div:nth-child(101) a > [data-btn-center-sel=poster] ale już movieLinkChild jest undefined

JSerwatka commented 9 months ago

Sprawdzałem:

Po spowolnieniu przy 100 filmie wyskakuje: "Error: Bład skryptu podczas ściągania oceny filmu" i w zakładce błędów, dostaję następujące rzeczy: image

@podwieczorekk @pgarbocz dajcie znać, czy coś takiego się u Was pojawia. Jeśli nie, to jest jeszcze jeden sposób, żeby sprawdzić co się dzieje. Jakby któryś z Was w ustawieniach prywatności na filmwebie zmienił "Moje oceny" na wszyscy i podesłał mi link do swojego konta (/user/#/votes/film) na adres jserwatka.dev@gmail.com (żeby uniknąć upubliczniania czegokolwiek). Jeśli wszystko pójdzie gładko, to odeślę Wam na tego samego maila export ocen, jeśli nie, to będę miał doskonały obiekt do znalezienia błędu.

pgarbocz commented 9 months ago

Próbowałem uruchomić ten skrypt na profilu publicznym jakiegokolwiek krytyka ale wtedy leci od razu błąd Uncaught (in promise) Error: Błąd skryptu: Target element not found. at getAllRates (:180:11) at async main (:254:18)

JSerwatka commented 9 months ago

Po 100 next_movie_selector zwraca div[data-group="userPage"] section > div:nth-child(2) > div:nth-child(101) a > [data-btn-center-sel=poster] ale już movieLinkChild jest undefined

Możliwe, że a > [data-btn-center-sel=poster] nie działa dla któregoś z filmów (niestety nie ma żadnego lepszego path, żeby to wyciągnąć), ale to nie tłumaczy, dlaczego dzieje się to zawsze po 100.

@pgarbocz Jakiś konkretny krytyk, żebyśmy mieli ten sam punkt odniesienia?

pgarbocz commented 9 months ago

Myślę że się nie obrazi: https://www.filmweb.pl/user/sobol4ever#/votes/film

Z tego co widze to paginacja jest zrobiona po 100 elementów na page, więc wygląda jakby z kolejnych stron nie potrafił ładować.

JSerwatka commented 9 months ago

@pgarbocz dobra, udało mi się odtworzyć to na innym kompie i koncie, biorę się do roboty

JSerwatka commented 9 months ago

Ok, mam nadzieję, że tym razem pójdzie

@pgarbocz @ozz2024 @podwieczorekk Sprawdźcie proszę tę wersję:

function loadAllInfiniteScrollChildren(allMoviesContainer, expectedChildCount) {
  function scrollToBottom() {
    window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
  }

  function checkIfAllElementsLoaded() {
    let allChildrenLoaded = Array.from(allMoviesContainer.children).every((child => {
      if (child.classList.length == 0 || child.classList.contains("hide")) {
        return true
      }
      return child.querySelector("[data-btn-center-sel=poster]")
    }))
    const currentChildCount = allMoviesContainer.children.length;

    if (currentChildCount >= expectedChildCount && allChildrenLoaded) {
      return true
    }
    return false
  }

  return new Promise((resolve, reject) => {
    if (!allMoviesContainer) {
      reject("Błąd skryptu: Target element not found.");
      return;
    }

    if (!expectedChildCount) {
      reject("Błąd skryptu: No children found");
      return;
    }

    if (checkIfAllElementsLoaded()) {
      resolve(allMoviesContainer.children);
    }

    const checkAndScroll = (mutationsList) => {
      for (const mutation of mutationsList) {
        if (checkIfAllElementsLoaded()) {
          // All expected children are now visible, scrolling is done
          scrollToBottom()

          observer.disconnect();
          resolve(allMoviesContainer.children);
        } else {
          scrollToBottom()
        }
      }
    };

    const observer = new MutationObserver(checkAndScroll);

    observer.observe(allMoviesContainer, { childList: true, subtree: true });

    // Initialize creating new children
    scrollToBottom();
  });
}

function formatDate(dateNumber) {
  const dateStr = dateNumber?.toString();
  if (!dateStr) {
    return `2000-01-01`
  }

  const year = dateStr.substring(0, 4);
  const month = dateStr.substring(4, 6);
  const day = dateStr.substring(6, 8);

  return `${year}-${month}-${day}`;
}

async function getMovieData(movieUrl) {
  const parser = new DOMParser();

  const DOMContent = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania danych filmu`);
      }
      return response.text();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!DOMContent) {
    return undefined;
  }

  const htmlDocument = parser.parseFromString(DOMContent, "text/html");

  let title = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__originalTitle"
  )?.textContent;
  if (!title) {
    title = htmlDocument.querySelector(
      ".filmCoverSection__titleDetails > .filmCoverSection__title"
    )?.textContent;
  }

  let year = htmlDocument.querySelector(
    ".filmCoverSection__titleDetails > .filmCoverSection__year"
  )?.textContent;
  year = year.split(" - ")[0]; // handle serial dates
  const movieId = htmlDocument.querySelector("[data-film-id]")?.dataset?.filmId;

  return {
    movieId,
    movieData: {
      Title: title.includes(",") ? `"${title}"` : title,
      Year: year,
    },
  };
}

async function getRatingData(movieId, contentType) {
  const movieUrl = `https://www.filmweb.pl/api/v1/logged/vote/${contentType}/${movieId}/details`;
  const ratingJSON = await fetch(movieUrl, {
    method: "GET",
    headers: {
      Cookie: document.cookie,
    },
  })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Bład skryptu podczas ściągania oceny filmu`);
      }
      return response.json();
    })
    .catch((error) => {
      console.log(error);
      return undefined;
    });

  if (!ratingJSON) {
    return undefined;
  }

  return {
    WatchedDate: formatDate(ratingJSON.viewDate),
    ...(ratingJSON.rate >= 1 && { Rating10: ratingJSON.rate }),
  };
}

async function waitForElement(baseElement, selector, timeout = 5000) {
  let timeoutId;

  return new Promise((resolve) => {
    if (baseElement.querySelector(selector)) {
      return resolve(baseElement.querySelector(selector));
    }

    const observer = new MutationObserver((mutations) => {
      if (baseElement.querySelector(selector)) {
        timeoutId && clearTimeout(timeoutId);
        observer.disconnect();
        resolve(baseElement.querySelector(selector));
      }
    });

    observer.observe(baseElement, {
      childList: true,
      subtree: true,
    });

    timeoutId = setTimeout(() => {
      observer.disconnect();
      resolve(undefined);
    }, timeout);
  });
}

async function getAllRates() {
  const contentType = window.location.href.split("/").pop();
  const allMoviesContainer = document.querySelector('div[data-group="userPage"]  section > div:nth-child(2)');
  const expectedChildCount = Number(
    document.querySelector(
      'div[data-group="userPage"] li > a.active[data-counter]'
    ).dataset.counter ?? ""
  );
  let allMoviesElements;
  try {
    allMoviesElements = await loadAllInfiniteScrollChildren(
      allMoviesContainer,
      expectedChildCount
    );
  } catch (error) {
    throw new Error(error);
  }
  const allRates = [];

  for (let i = 0; i <= expectedChildCount - 1; i++) {
    const movieLink = allMoviesElements[i].querySelector("a")?.href;

    try {
      if (!movieLink) {
        console.log("HTML: ", allMoviesElements[i]);
        console.log("index: ", i);
        throw Error("Nie znaleziono filmu");
      }

      const { movieId, movieData } = await getMovieData(movieLink);
      if (!movieId || !movieData) {
        continue;
      }
      const ratingData = await getRatingData(movieId, contentType);

      allRates.push({ ...movieData, ...ratingData });
    } catch (e) {
      console.log(e);
      return allRates;
    }
    console.log("pobrano " + (i + 1) + " z " + expectedChildCount);
  }
  return allRates;
}

function download(filename, text) {
  const element = document.createElement("a");
  element.setAttribute(
    "href",
    "data:text/plain;charset=utf-8," + encodeURIComponent(text)
  );
  element.setAttribute("download", filename);
  element.style.display = "none";
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

function arrayToCsv(allRates) {
  let csvRates = Object.keys(allRates[0]).join(",") + "\n";
  let filesArray = [];

  for (let i = 0; i < allRates.length; i++) {
    // Split csv for rate count > 1800
    if (i % 1799 == 0 && i > 0) {
      filesArray.push(csvRates);
      csvRates = Object.keys(allRates[0]).join(",") + "\n";
    }
    csvRates += Object.values(allRates[i]).join(",");
    csvRates += "\n";
  }
  filesArray.push(csvRates);

  return filesArray;
}

async function main() {
  console.log("Rozpoczynam pobieranie, cierpliwości...");
  console.log("Proszę nie zamykać, przełączać, ani minimalizować tego okna!");
  let allRates = await getAllRates();
  console.log("rozpoczynam ściąganie pliku csv");
  let csvRates = arrayToCsv(allRates);

  for (let i = 0; i < csvRates.length; i++) {
    download(`Filmweb2Letterboxd_watched_${i}.csv`, csvRates[i]);
  }
}

main();
pgarbocz commented 9 months ago

@JSerwatka teraz śmiga, dzięki wielkie!

Może warto do readme dodać poradę, żeby po analizie importu na letterboxd, zaznaczyć checkboxa Hide successful matches, bo wtedy można wyłapać te których nie znalazł i powprowadzać im prawidłowe nazwy. Czasem po prostu po tytule z filmweba nie potrafi odnaleźć na letterboxd.

pgarbocz commented 9 months ago

A seriali nie polecam na razie importować, bo nie istnieją w letterboxd i mapuje do najbardziej pasujących tytułów, ale ogłosili że w tym roku dodadzą seriale.

ozz2024 commented 9 months ago

Mi wciąż nie działa, ani n Chrome, ani na Mozilli. :(

JSerwatka commented 9 months ago

@pgarbocz

Może warto do readme dodać poradę, żeby po analizie importu na letterboxd, zaznaczyć checkboxa Hide successful matches, bo wtedy można wyłapać te których nie znalazł i powprowadzać im prawidłowe nazwy. Czasem po prostu po tytule z filmweba nie potrafi odnaleźć na letterboxd.

Dzięki, dobry pomysł. Ja wyciągam najpierw oryginalny tytuł, bo w letterboxd szukanie po tytule polskim jest co najmniej problematyczne

A seriali nie polecam na razie importować, bo nie istnieją w letterboxd i mapuje do najbardziej pasujących tytułów, ale ogłosili że w tym roku dodadzą seriale.

Potwierdzam, że z serialami jest kompletny chaos, ale dobrze, że wreszcie to łatają

W ogóle jestem w trakcie robienia rozszerzenia do Chroma łatającego wiele problemów letterboxd, więc stay tuned

JSerwatka commented 9 months ago

@ozz2024 Spojrzę jeszcze jutro lub pojutrze na to. Na razie robiłem takie łatanie na szybko.

ozz2024 commented 9 months ago

Spróbowałam na komputerze stacjonarnym i wszystko dobrze działa. To musiał być problem z moim laptopem. Oba mają windows.

JSerwatka commented 9 months ago

@ozz2024 dzięki za info, zobaczę co da się zrobić, żeby działało tak samo, niezależnie od sprzętu