fix wait for animation end (#3201)
This commit is contained in:
@@ -2642,6 +2642,28 @@ async function getIncrementElements(wait_until_finished = true) {
|
|||||||
return [Array.from(idToElement.values()), cleanedTreeList];
|
return [Array.from(idToElement.values()), cleanedTreeList];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAnimationFinished() {
|
||||||
|
const animations = document.getAnimations({ subtree: true });
|
||||||
|
const unfinishedAnimations = animations.filter(
|
||||||
|
(a) => a.playState !== "finished",
|
||||||
|
);
|
||||||
|
if (!unfinishedAnimations || unfinishedAnimations.length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const unfinishedAnimationsWithoutBlocked = unfinishedAnimations.filter(
|
||||||
|
(a) => {
|
||||||
|
const element = a.effect?.target;
|
||||||
|
if (!element) {
|
||||||
|
_jsConsoleLog("Unfinished animation without element:", a);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const result = getBlockElementUniqueID(element);
|
||||||
|
return !result[1];
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return unfinishedAnimationsWithoutBlocked.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
// How to run the code:
|
// How to run the code:
|
||||||
|
|||||||
@@ -557,7 +557,8 @@ async def scrape_web_unsafe(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await page.wait_for_load_state("load", timeout=3000)
|
await page.wait_for_load_state("load", timeout=3000)
|
||||||
await SkyvernFrame.wait_for_animation_end(page)
|
skyvern_frame = await SkyvernFrame.create_instance(page)
|
||||||
|
await skyvern_frame.safe_wait_for_animation_end()
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning("Failed to wait for load state, will continue scraping", exc_info=True)
|
LOG.warning("Failed to wait for load state, will continue scraping", exc_info=True)
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ async def _scrolling_screenshots_helper(
|
|||||||
|
|
||||||
if mode == ScreenshotMode.DETAILED:
|
if mode == ScreenshotMode.DETAILED:
|
||||||
# wait until animation ends, which is triggered by scrolling
|
# wait until animation ends, which is triggered by scrolling
|
||||||
await SkyvernFrame.wait_for_animation_end(skyvern_page.frame)
|
await skyvern_page.safe_wait_for_animation_end()
|
||||||
else:
|
else:
|
||||||
if draw_boxes:
|
if draw_boxes:
|
||||||
await skyvern_page.build_elements_and_draw_bounding_boxes(frame=frame, frame_index=frame_index)
|
await skyvern_page.build_elements_and_draw_bounding_boxes(frame=frame, frame_index=frame_index)
|
||||||
@@ -214,21 +214,6 @@ def _merge_images_by_position(images: list[Image.Image], positions: list[int]) -
|
|||||||
|
|
||||||
|
|
||||||
class SkyvernFrame:
|
class SkyvernFrame:
|
||||||
@staticmethod
|
|
||||||
async def wait_for_animation_end(page: Page, timeout: float = 3000) -> None:
|
|
||||||
try:
|
|
||||||
await page.wait_for_function(
|
|
||||||
"""
|
|
||||||
() => {
|
|
||||||
const animations = document.getAnimations();
|
|
||||||
return animations.every(a => a.playState === 'finished');
|
|
||||||
}
|
|
||||||
""",
|
|
||||||
timeout=timeout,
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
LOG.warning("Failed to wait for animation end, but continue", exc_info=True)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def evaluate(
|
async def evaluate(
|
||||||
frame: Page | Frame,
|
frame: Page | Frame,
|
||||||
@@ -514,3 +499,23 @@ class SkyvernFrame:
|
|||||||
return await self.evaluate(
|
return await self.evaluate(
|
||||||
frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[wait_until_finished]
|
frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[wait_until_finished]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def safe_wait_for_animation_end(self, timeout_ms: float = 3000) -> None:
|
||||||
|
try:
|
||||||
|
async with asyncio.timeout(timeout_ms / 1000):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
is_finished = await self.evaluate(
|
||||||
|
frame=self.frame,
|
||||||
|
expression="() => isAnimationFinished()",
|
||||||
|
timeout_ms=timeout_ms,
|
||||||
|
)
|
||||||
|
if is_finished:
|
||||||
|
return
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
except Exception:
|
||||||
|
LOG.warning("Failed to wait for animation end, but ignore it", exc_info=True)
|
||||||
|
return
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
LOG.debug("Timeout while waiting for animation end, but ignore it", exc_info=True)
|
||||||
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user