Używam PhantomJS v1.4.1 do ładowania niektórych stron internetowych. Nie mam dostępu do ich serwera, po prostu otrzymuję odsyłacze do nich. Używam przestarzałej wersji Phantoma, ponieważ muszę obsługiwać Adobe Flash na tych stronach internetowych.
Problem polega na tym, że wiele stron internetowych ładuje mniejszą zawartość asynchronicznie i dlatego wywołanie zwrotne onLoadFinished Phantoma (analog dla onLoad w HTML) uruchomiło się zbyt wcześnie, gdy nie wszystko zostało jeszcze załadowane. Czy ktoś może zasugerować, jak mogę czekać na pełne załadowanie strony internetowej, aby na przykład zrobić zrzut ekranu z całą zawartością dynamiczną, taką jak reklamy?
javascript
events
phantomjs
nilfalse
źródło
źródło
Odpowiedzi:
Innym podejściem jest po prostu poproszenie PhantomJS, aby poczekał chwilę po załadowaniu strony przed wykonaniem renderowania, jak w zwykłym przykładzie rasterize.js , ale z dłuższym limitem czasu, aby umożliwić JavaScriptowi zakończenie ładowania dodatkowych zasobów:
źródło
Wolałbym okresowo sprawdzać
document.readyState
status ( https://developer.mozilla.org/en-US/docs/Web/API/document.readyState ). Chociaż takie podejście jest trochę niezgrabne, możesz być pewien, że wewnątrzonPageReady
funkcji używasz w pełni załadowanego dokumentu.Dodatkowe wyjaśnienie:
Używanie zagnieżdżonych
setTimeout
zamiastsetInterval
zapobieganiacheckReadyState
"nakładaniu się" i warunków wyścigu, gdy jego wykonanie jest przedłużane z pewnych przypadkowych powodów.setTimeout
ma domyślne opóźnienie 4 ms ( https://stackoverflow.com/a/3580085/1011156 ), więc aktywne odpytywanie nie wpłynie drastycznie na wydajność programu.document.readyState === "complete"
oznacza, że dokument jest całkowicie załadowany wszystkimi zasobami ( https://html.spec.whatwg.org/multipage/dom.html#current-document-readiness ).źródło
readyState
uruchomi się tylko wtedy, gdy DOM zostanie w pełni załadowany, jednak wszelkie<iframe>
elementy mogą nadal się ładować, więc tak naprawdę nie odpowiada na oryginalne pytanieMożesz spróbować kombinacji przykładów waitfor i rasterize:
źródło
Może możesz użyć wywołań zwrotnych
onResourceRequested
ionResourceReceived
do wykrywania ładowania asynchronicznego. Oto przykład użycia tych wywołań zwrotnych z ich dokumentacji :Możesz również spojrzeć na
examples/netsniff.js
działający przykład.źródło
All the resource requests and responses can be sniffed using onResourceRequested and onResourceReceived
Oto rozwiązanie, które czeka na zakończenie wszystkich żądań zasobów. Po zakończeniu zarejestruje zawartość strony w konsoli i wygeneruje zrzut ekranu renderowanej strony.
Chociaż to rozwiązanie może służyć jako dobry punkt wyjścia, zauważyłem, że zawodzi, więc zdecydowanie nie jest to rozwiązanie kompletne!
Nie miałem szczęścia przy używaniu
document.readyState
.Wpływ na mnie miał przykład waitfor.js, który można znaleźć na stronie przykładów phantomjs .
źródło
W moim programie używam logiki, aby ocenić, czy był on załadowany: obserwując żądanie sieciowe, jeśli nie było nowego żądania w ciągu ostatnich 200 ms, traktuję je jako załadowane.
Użyj tego po onLoadFinish ().
źródło
Uważam, że to podejście jest przydatne w niektórych przypadkach:
Jeśli jesteś właścicielem strony, umieść w niej skrypt:
źródło
Znalazłem to rozwiązanie przydatne w aplikacji NodeJS. Używam go tylko w rozpaczliwych przypadkach, ponieważ uruchamia limit czasu, aby poczekać na pełne załadowanie strony.
Drugim argumentem jest funkcja zwrotna, która zostanie wywołana, gdy odpowiedź będzie gotowa.
źródło
To jest implementacja odpowiedzi Supr. Używa również setTimeout zamiast setInterval, jak sugerował Mateusz Charytoniuk.
Phantomjs zakończy działanie po 1000 ms, gdy nie będzie żadnego żądania ani odpowiedzi.
źródło
Oto kod, którego używam:
Zasadniczo, biorąc pod uwagę fakt, że powinieneś wiedzieć, że strona jest pobierana w całości, gdy dany element pojawia się w DOM. Więc skrypt będzie czekał, aż to się stanie.
źródło
Używam personalnej mieszanki
waitfor.js
przykładu phantomjs .To jest mój
main.js
plik:I
lib/waitFor.js
plik (który jest po prostu kopiowaniem i wklejaniemwaifFor()
funkcji zwaitfor.js
przykładu phantomjs ):Ta metoda nie jest asynchroniczna, ale przynajmniej mam pewność, że wszystkie zasoby zostały załadowane, zanim spróbuję ich użyć.
źródło
To stare pytanie, ale ponieważ szukałem pełnego załadowania strony, ale Spookyjs (który używa casperjs i phantomjs) i nie znalazłem swojego rozwiązania, stworzyłem własny skrypt, z tym samym podejściem, jakie uważa użytkownik. To podejście polega na tym, że przez określony czas, jeśli strona nie otrzymała lub nie rozpoczęła żadnego żądania, zakończy wykonywanie.
W pliku casper.js (jeśli zainstalowałeś go globalnie, ścieżka wyglądałaby tak, jak /usr/local/lib/node_modules/casperjs/modules/casper.js) dodaj następujące wiersze:
U góry pliku ze wszystkimi globalnymi zmiennymi:
Następnie wewnątrz funkcji "createPage (casper)" zaraz po "var page = require ('webpage'). Create ();" dodaj następujący kod:
Następnie wewnątrz „page.onResourceReceived = function onResourceReceived (resource) {” w pierwszym wierszu dodaj:
Zrób to samo dla "page.onResourceRequested = function onResourceRequested (requestData, request) {"
Na koniec w „page.onLoadFinished = function onLoadFinished (status) {” w pierwszym wierszu dodaj:
I to wszystko, mam nadzieję, że ten pomoże komuś w tarapatach, tak jak ja. To rozwiązanie jest przeznaczone dla casperjs, ale działa bezpośrednio dla Spooky.
Powodzenia !
źródło
to jest moje rozwiązanie, które zadziałało dla mnie.
źródło