helper function for wait animation (#3240)
This commit is contained in:
@@ -974,18 +974,7 @@ async def handle_input_text_action(
|
|||||||
action=action,
|
action=action,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end()
|
||||||
await skyvern_frame.get_frame().wait_for_load_state("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Timeout to wait for the frame to load, ignore the timeout and continue to execute the action",
|
|
||||||
task_id=task.task_id,
|
|
||||||
step_id=step.step_id,
|
|
||||||
element_id=skyvern_element.get_id(),
|
|
||||||
action=action,
|
|
||||||
)
|
|
||||||
|
|
||||||
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
||||||
clean_and_remove_element_tree_factory(
|
clean_and_remove_element_tree_factory(
|
||||||
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
||||||
@@ -1126,18 +1115,7 @@ async def handle_input_text_action(
|
|||||||
return [ActionFailure(InvalidElementForTextInput(element_id=action.element_id, tag_name=tag_name))]
|
return [ActionFailure(InvalidElementForTextInput(element_id=action.element_id, tag_name=tag_name))]
|
||||||
|
|
||||||
# wait for blocking element to show up
|
# wait for blocking element to show up
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end()
|
||||||
await skyvern_frame.get_frame().wait_for_load_state("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Timeout to wait for the frame to load, ignore the timeout and continue to execute the action",
|
|
||||||
task_id=task.task_id,
|
|
||||||
step_id=step.step_id,
|
|
||||||
element_id=skyvern_element.get_id(),
|
|
||||||
action=action,
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
blocking_element, exist = await skyvern_element.find_blocking_element(
|
blocking_element, exist = await skyvern_element.find_blocking_element(
|
||||||
dom=dom, incremental_page=incremental_scraped
|
dom=dom, incremental_page=incremental_scraped
|
||||||
@@ -1538,15 +1516,7 @@ async def handle_select_option_action(
|
|||||||
|
|
||||||
await skyvern_element.click(page=page, dom=dom, timeout=timeout)
|
await skyvern_element.click(page=page, dom=dom, timeout=timeout)
|
||||||
# wait for options to load
|
# wait for options to load
|
||||||
await asyncio.sleep(0.5)
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
try:
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the frame to load, ignore the timeout and continue to get incremental element tree",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
||||||
clean_and_remove_element_tree_factory(
|
clean_and_remove_element_tree_factory(
|
||||||
@@ -1564,15 +1534,7 @@ async def handle_select_option_action(
|
|||||||
await skyvern_element.scroll_into_view()
|
await skyvern_element.scroll_into_view()
|
||||||
await skyvern_element.press_key("ArrowDown")
|
await skyvern_element.press_key("ArrowDown")
|
||||||
# wait for options to load
|
# wait for options to load
|
||||||
await asyncio.sleep(0.5)
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
try:
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the frame to load, ignore the timeout and continue to get incremental element tree",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
||||||
clean_and_remove_element_tree_factory(
|
clean_and_remove_element_tree_factory(
|
||||||
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
||||||
@@ -1669,15 +1631,7 @@ async def handle_select_option_action(
|
|||||||
await skyvern_element.scroll_into_view()
|
await skyvern_element.scroll_into_view()
|
||||||
await skyvern_element.press_key("ArrowDown")
|
await skyvern_element.press_key("ArrowDown")
|
||||||
|
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the frame to load, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
is_open = True
|
is_open = True
|
||||||
|
|
||||||
result = await select_from_dropdown_by_value(
|
result = await select_from_dropdown_by_value(
|
||||||
@@ -2200,15 +2154,7 @@ async def choose_auto_completion_dropdown(
|
|||||||
try:
|
try:
|
||||||
await skyvern_element.press_fill(text)
|
await skyvern_element.press_fill(text)
|
||||||
# wait for new elemnts to load
|
# wait for new elemnts to load
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_load_state("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.warning(
|
|
||||||
"Failed to wait for load state or animation end after input the value, will continue to get incremental element tree",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
incremental_element = await incremental_scraped.get_incremental_element_tree(
|
||||||
clean_and_remove_element_tree_factory(
|
clean_and_remove_element_tree_factory(
|
||||||
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
task=task, step=step, check_filter_funcs=[check_existed_but_not_option_element_in_dom_factory(dom)]
|
||||||
@@ -2608,15 +2554,7 @@ async def sequentially_select_from_dropdown(
|
|||||||
select_history.append(single_select_result)
|
select_history.append(single_select_result)
|
||||||
values.append(single_select_result.value)
|
values.append(single_select_result.value)
|
||||||
# wait 1s until DOM finished updating
|
# wait 1s until DOM finished updating
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the animation to end, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
if await single_select_result.is_done():
|
if await single_select_result.is_done():
|
||||||
return single_select_result
|
return single_select_result
|
||||||
@@ -2637,15 +2575,7 @@ async def sequentially_select_from_dropdown(
|
|||||||
step_id=step.step_id,
|
step_id=step.step_id,
|
||||||
)
|
)
|
||||||
# wait to load new options
|
# wait to load new options
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the animation to end, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
check_filter_funcs.append(
|
check_filter_funcs.append(
|
||||||
check_disappeared_element_id_in_incremental_factory(incremental_scraped=incremental_scraped)
|
check_disappeared_element_id_in_incremental_factory(incremental_scraped=incremental_scraped)
|
||||||
@@ -3356,29 +3286,13 @@ async def scroll_down_to_load_all_options(
|
|||||||
else:
|
else:
|
||||||
await skyvern_frame.scroll_to_element_bottom(dropdown_menu_element_handle, page_by_page)
|
await skyvern_frame.scroll_to_element_bottom(dropdown_menu_element_handle, page_by_page)
|
||||||
# wait until animation ends, otherwise the scroll operation could be overwritten
|
# wait until animation ends, otherwise the scroll operation could be overwritten
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the animation to end, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# scroll a little back and scroll down to trigger the loading
|
# scroll a little back and scroll down to trigger the loading
|
||||||
await page.mouse.wheel(0, -1e-5)
|
await page.mouse.wheel(0, -1e-5)
|
||||||
await page.mouse.wheel(0, 1e-5)
|
await page.mouse.wheel(0, 1e-5)
|
||||||
# wait for while to load new options
|
# wait for while to load new options
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the animation to end, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
current_num = await incremental_scraped.get_incremental_elements_num()
|
current_num = await incremental_scraped.get_incremental_elements_num()
|
||||||
LOG.info(
|
LOG.info(
|
||||||
@@ -3403,15 +3317,7 @@ async def scroll_down_to_load_all_options(
|
|||||||
await page.mouse.wheel(0, -scroll_pace)
|
await page.mouse.wheel(0, -scroll_pace)
|
||||||
else:
|
else:
|
||||||
await skyvern_frame.scroll_to_element_top(dropdown_menu_element_handle)
|
await skyvern_frame.scroll_to_element_top(dropdown_menu_element_handle)
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end(before_wait_sec=0.5)
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
await skyvern_frame.get_frame().wait_for_event("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.info(
|
|
||||||
"Failed to wait for the animation to end, ignore the exception and continue",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def normal_select(
|
async def normal_select(
|
||||||
|
|||||||
@@ -555,12 +555,8 @@ async def scrape_web_unsafe(
|
|||||||
if url == "about:blank" and not support_empty_page:
|
if url == "about:blank" and not support_empty_page:
|
||||||
raise ScrapingFailedBlankPage()
|
raise ScrapingFailedBlankPage()
|
||||||
|
|
||||||
try:
|
skyvern_frame = await SkyvernFrame.create_instance(page)
|
||||||
await page.wait_for_load_state("load", timeout=3000)
|
await skyvern_frame.safe_wait_for_animation_end()
|
||||||
skyvern_frame = await SkyvernFrame.create_instance(page)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.warning("Failed to wait for load state, will continue scraping", exc_info=True)
|
|
||||||
|
|
||||||
if wait_seconds > 0:
|
if wait_seconds > 0:
|
||||||
LOG.info(f"Waiting for {wait_seconds} seconds before scraping the website.", wait_seconds=wait_seconds)
|
LOG.info(f"Waiting for {wait_seconds} seconds before scraping the website.", wait_seconds=wait_seconds)
|
||||||
@@ -689,15 +685,7 @@ async def add_frame_interactable_elements(
|
|||||||
return elements, element_tree
|
return elements, element_tree
|
||||||
|
|
||||||
skyvern_frame = await SkyvernFrame.create_instance(frame)
|
skyvern_frame = await SkyvernFrame.create_instance(frame)
|
||||||
try:
|
await skyvern_frame.safe_wait_for_animation_end()
|
||||||
await skyvern_frame.get_frame().wait_for_load_state("load", timeout=3000)
|
|
||||||
await skyvern_frame.safe_wait_for_animation_end()
|
|
||||||
except Exception:
|
|
||||||
LOG.warning(
|
|
||||||
"Failed to wait for load state or animation end for the frame, will continue scraping",
|
|
||||||
frame_id=unique_id,
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
frame_elements, frame_element_tree = await skyvern_frame.build_tree_from_body(
|
frame_elements, frame_element_tree = await skyvern_frame.build_tree_from_body(
|
||||||
frame_name=unique_id, frame_index=frame_index
|
frame_name=unique_id, frame_index=frame_index
|
||||||
|
|||||||
@@ -517,22 +517,23 @@ class SkyvernFrame:
|
|||||||
frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[starter, frame, full_tree]
|
frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[starter, frame, full_tree]
|
||||||
)
|
)
|
||||||
|
|
||||||
async def safe_wait_for_animation_end(self, timeout_ms: float = 3000) -> None:
|
async def safe_wait_for_animation_end(self, before_wait_sec: float = 0, timeout_ms: float = 3000) -> None:
|
||||||
try:
|
try:
|
||||||
async with asyncio.timeout(timeout_ms / 1000):
|
await asyncio.sleep(before_wait_sec)
|
||||||
while True:
|
await self.frame.wait_for_load_state("load", timeout=timeout_ms)
|
||||||
try:
|
await self.wait_for_animation_end(timeout_ms=timeout_ms)
|
||||||
is_finished = await self.evaluate(
|
except Exception:
|
||||||
frame=self.frame,
|
LOG.info("Failed to wait for animation end, but ignore it", exc_info=True)
|
||||||
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
|
return
|
||||||
|
|
||||||
|
async def wait_for_animation_end(self, timeout_ms: float = 3000) -> None:
|
||||||
|
async with asyncio.timeout(timeout_ms / 1000):
|
||||||
|
while True:
|
||||||
|
is_finished = await self.evaluate(
|
||||||
|
frame=self.frame,
|
||||||
|
expression="() => isAnimationFinished()",
|
||||||
|
timeout_ms=timeout_ms,
|
||||||
|
)
|
||||||
|
if is_finished:
|
||||||
|
return
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|||||||
Reference in New Issue
Block a user