def test_complex(): @wtl.single_tab def policy(w, view): menu_actions = view.actions.by_type(Click).by_score("menu") w.metadata["clicks"] = w.metadata["clicks"] + 1 return random.choice(menu_actions) def menu_classifier_func(elements, _): return [ elem for elem in elements if elem.location.x < 10 and elem.location.y < 200 and elem.metadata["tag"] == "a" ] config = Config.default(["headless", "desktop"]) workflow = wtl.Workflow(url=TESTURL, config=config, policy=policy, goal=wtl.goals.N_STEPS(3)) workflow.metadata["clicks"] = 0 workflow.classifiers.add(wtl.ActiveElementFilter(action=Click)) workflow.classifiers.add( wtl.ElementClassifier(name="menu", action=Click, subset="is_active", highlight=True, callback=menu_classifier_func)) workflow.run() assert workflow.success assert workflow.metadata["clicks"] == 3 workflow.quit()
def wtl_thread(cli_args): workflow = wtl.Workflow(config=wtl.Config(cli_args.config), policy=policy, url=cli_args.url, output=cli_args.output) workflow.classifiers.add(wtl.ActiveElementFilter(action=wtl.actions.Click, highlight=True)) workflow.run() workflow.quit()
def _start_btn(elements, _): return [e for e in elements if e.metadata["id"] == "sync-task-cover" and "block" in e.metadata["display"]] def _tile_div(elements, _): return [ e for e in elements if e.metadata["tag"] == "span" and e.metadata["id"].startswith("ttt") and e.tag.parent.name == "div" ] if __name__ == "__main__": cli_args = parse_cli_args() workflow = wtl.Workflow( config=wtl.Config(cli_args.config), policy=policy, url="https://stanfordnlp.github.io/miniwob-plusplus/html/miniwob/tic-tac-toe.html", output=cli_args.output, ) workflow.classifiers.add(wtl.ActiveElementFilter()) workflow.classifiers.add(wtl.ActiveElementFilter(name="start", callback=_start_btn, action=Click)) workflow.classifiers.add(wtl.ActiveElementFilter(name="tile", callback=_tile_div, action=Click)) workflow.run() workflow.quit()
from .util import parse_cli_args @wtl.single_tab def policy(workflow: wtl.Workflow, view: wtl.View) -> wtl.Action: assert workflow.duplicate_loop_idx == workflow.loop_idx # With some small probabilty, refresh instead of clicking. return choice(view.actions.by_type( Click)) if random() < 0.95 else view.actions.by_type(Refresh).unique() def set_duplicate_loop_idx(workflow: wtl.Workflow): workflow.duplicate_loop_idx = workflow.loop_idx if __name__ == "__main__": cli_args = parse_cli_args() wf = wtl.Workflow(config=wtl.Config(cli_args.config), policy=policy, url=cli_args.url, output=cli_args.output) wf.classifiers.add(wtl.ActiveElementFilter(action=Click)) wf.postload_callbacks.append(partial(set_duplicate_loop_idx, wf)) wf.run() wf.quit()
def text_field_classifier_func(elements: wtl.Elements, _) -> List[wtl.PageElement]: return [ e for e in elements if e.metadata["tag"] == "input" and e.metadata["type"] in ("text", "email", "password") ] if __name__ == "__main__": cli_args = parse_cli_args() workflow = wtl.Workflow(config=wtl.Config(cli_args.config), policy=policy, url=cli_args.url, output=cli_args.output) workflow.classifiers.add(wtl.ActiveElementFilter(action=wtl.actions.Click)) workflow.classifiers.add( wtl.ElementClassifier(name="textfield", action=wtl.actions.FillText, callback=text_field_classifier_func, highlight=True)) logging.getLogger("wtl").setLevel(logging.CRITICAL) workflow.run() workflow.quit()
def score(element): return element.bounds.area / largest_area return { "big": [(e, score(e)) for e in elements if score(e) > 0.75], "average": [(e, abs(0.5 - score(e))) for e in elements if 0.25 < score(e) <= 0.75], } if __name__ == "__main__": cli_args = parse_cli_args() workflow = wtl.Workflow(config=wtl.Config(cli_args.config), policy=policy, url=cli_args.url, output=cli_args.output) workflow.classifiers.add(wtl.ActiveElementFilter()) workflow.classifiers.add( wtl.ElementClassifier(name="size", subset="is_active", highlight=0.5, action=Click, callback=size_classifier_func)) with workflow: workflow.run()