Scrape obrazów z canvas ze strony internetowej

0

Witajcie, pytanie dotyczy możliwości pobierania obrazów generowanych przez canvas. Chciałbym pobierać sobie obrazki ze strony: https://zehfernandes.com/generativeplanets/builder (przez Greasemonkey-a) - na użytek prywatny.

Przerobiłem do tej pory toDataURL, ale w przypadku grafik z powyższej strony ta metoda nie zadziała - zwraca pusty obraz. Czy istnieje jakaś możliwość pobrania snapshota takiej animowanej grafiki przy pomocy JS?

0

Próbowałeś wpisać w google "greasemonkey scrape canvas"?

0
Riddle napisał(a):

Próbowałeś wpisać w google "greasemonkey scrape canvas"?

Tak, siedzę nad tym od 2-ch dni i sprawdzałem różne sposoby. W przypadku statycznych canvasów nie ma problemu, jedynie z tym animowanym coś nie działa. Sprawdzałem też kilka wtyczek do przeglądarek, ale w takim przypadku grafika albo jest pusta, albo np. ucięta w połowie

0
catshy napisał(a):
Riddle napisał(a):

Próbowałeś wpisać w google "greasemonkey scrape canvas"?

Tak, siedzę nad tym od 2-ch dni i sprawdzałem różne sposoby. W przypadku statycznych canvasów nie ma problemu, jedynie z tym animowanym coś nie działa. Sprawdzałem też kilka wtyczek do przeglądarek, ale w takim przypadku grafika albo jest pusta, albo np. ucięta w połowie

A po co dokładnie próbujesz zapisać te animowane canvas?

0

@Riddle mi właściwie zależy na statycznym obrazie, one są anonimowane na tej stronie. Moje dzieciaki lubią temat kosmosu, planet itd. i chcę im z tych planet porobić różne zabawki w JS, typu minigierki jak memory z odkrywaniem kart, jakieś tam puzzle i inne tego typu. Chciałbym żeby była duża unikatowość tych obrazów i przydałoby mi się tak z kilkaset, a ręczne screenowanie i wycinanie tła to byłaby trochę robota głupiego

1

To chyba lepiej by było odpalić selenium, wchodzić na tą stronę np 1000 razy, i zapisywać screenshot.

Tu masz kod python który mógłby to zrobić.

from selenium import webdriver

for i in range(0, 1000):
  driver = webdriver.Chrome(executable_path = 'path\to\chromedriver.exe')
  driver.get("https://zehfernandes.com/generativeplanets/builder")
  driver.save_screenshot('planet.' + str(i) + '.png')

Jakbyś chciał kliknąć na "New random planet", to wywołaj:

driver.find_element_by_css_selector('span.property-name').click()

Tutaj jest opis jak to zrobić: https://www.browserstack.com/guide/take-screenshot-with-selenium-python

0

Spróbuj Puppeteer.

Co do pustego obrazu, może włączyła się polityka bezpieczeństwa
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
Przeczytaj fragment o SecurityError

1

Jeśli Twoim celem jest faktycznie zrobić to z kontekstu przeglądarki, to tworząc skrypt do greasemonkey, (czy też tempermonkey) musisz zadbać o kilka rzeczy:

Tak, siedzę nad tym od 2-ch dni i sprawdzałem różne sposoby. W przypadku statycznych canvasów nie ma problemu, jedynie z tym animowanym coś nie działa. Sprawdzałem też kilka wtyczek do przeglądarek, ale w takim przypadku grafika albo jest pusta, albo np. ucięta w połowie

  • przede wszystkim, przed stworzeniem contextu webgl, musisz wymusić by był on stworzony z zachowaniem bufora. Dlatego w cyklu życia strony i też skryptu, musisz jak najwcześniej podmienić metodę getContext np. poprzez nadpisanie prototypu HTMLCanvasElement
    Przykład:

    HTMLCanvasElement.prototype.getContext = function(origFn) {
      return function(type, attributes) {
        if (type === 'webgl') {
          attributes = Object.assign({}, attributes, {
            preserveDrawingBuffer: true,
          });
        }
        return origFn.call(this, type, attributes);
      };
    }(HTMLCanvasElement.prototype.getContext);
    

    To powinno zapobiec czyszczeniu bufora w trakcie transformacji do obrazka

  • następnie możesz stworzyć bloba i zemulować ściąganie pliku poprzez atrybut download dostępny na linkach w HTML5, ale to już pewnie wiesz, skoro dostawałeś wcześniej puste obrazki ;)
    PoC:

    const data = document.querySelector('#canvas-planet').toDataURL()
    fetch(data).then((b) => b.blob())
    .then(blob => {
        saveFile('planet.png', blob);
    });
    
    function saveFile(fileName,blob){
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.style = "display: none";
        document.body.appendChild(a);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
        a.remove();
    }
    
0

toDataURL czasami wyrzuca pusty obraz, szczegolnie jesli chodzi o grafiki z zabezpieczeniami lub jesli canvas zostal "zanieczyszczony" przez dane z innych zrodel. mozliwe, ze to wlasnie problem tkwi tutaj. ale spoko, sa inne sposoby. 😎 mozna sprobowac toBlob - to tez pozwala na sciaganie obrazkow z canvas, tyle ze nie jest az tak znana. ale jak masz do czynienia z animacja i chcesz snapshot w konkretnym momencie, to znowu, wyzwanie - trzeba trafic w ten wlasciwy frame.co mozesz zrobic, to ustawic w JS interwal, ktory bedzie probowal zlapac klatke w dobrym czasie. 🤔 tylko warto uwazac, zeby nie przesadzic z czestoscia, bo mozna spowolnic dzialanie strony.
jesli chodzi o greasemonkey, to pamietaj, zeby wszystko robic ostroznie. skrypty uzytkownika sa super do personalizowania doswiadczen w necie, ale latwo cos popsuc. 🙈 jak juz bedziesz gotowy poeksperymentowac z JS, warto poczytac o canvas API. znajdziesz tam rozne eventy i metody, ktore moga ci pomoc w twoim projekcie. w koncu czlowiek sie uczy całe zycie.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.