async def read_page(browserurl, targeturl): """ read a page and get the title originally https://github.com/HyperionGray/trio-chrome-devtools-protocol/blob/master/examples/get_title.py """ logger.info("Connecting to browser: %s", browserurl) async with open_cdp(browserurl) as conn: logger.info("Listing targets") targets = await conn.execute(target.get_targets()) target_id = targets[0].target_id logger.info("Attaching to target id=%s", target_id) session = await conn.open_session(target_id) logger.info("Navigating to %s", targeturl) await session.execute(page.enable()) async with session.wait_for(page.LoadEventFired): await session.execute(page.navigate(targeturl)) _, item = await session.execute(page.print_to_pdf()) print(f"pdf is: {type(item)}") logger.info("Extracting page title") root_node = await session.execute(dom.get_document()) title_node_id = await session.execute( dom.query_selector(root_node.node_id, "title") ) html = await session.execute(dom.get_outer_html(title_node_id))
async def test_connection_browser_error(nursery): ''' If the browser sends an error with a valid command ID, then that error should be raised at the point where the command was executed. Compare to ``test_connection_invalid_json()``, where the error is raised on the reader task since there is no way to associate it with a specific commmand. ''' async def handler(request): # It's tricky to catch exceptions from the server, so exceptions # are logged instead. try: ws = await request.accept() command = json.loads(await ws.get_message()) logging.info('Server received: %r', command) response = { 'id': command['id'], 'error': { 'code': -32000, 'message': 'This is a browser error', 'data': 'This is additional data' } } logging.info('Server sending reponse: %r', response) await ws.send_message(json.dumps(response)) except Exception: logging.exception('Server exception') server = await start_server(nursery, handler) async with open_cdp(server) as conn: with pytest.raises(BrowserError) as exc_info: targets = await conn.execute(target.get_targets()) assert exc_info.value.code == -32000
async def test_connection_execute(nursery): ''' Open a connection and execute a command on it. ''' async def handler(request): # It's tricky to catch exceptions from the server, so exceptions are # logged instead. try: ws = await request.accept() command = json.loads(await ws.get_message()) logging.info('Server received: %r', command) assert command['method'] == 'Target.getTargets' response = { 'id': command['id'], 'result': { 'targetInfos': [{ 'targetId': 'target1', 'type': 'tab', 'title': 'New Tab', 'url': 'about:newtab', 'attached': False, }], } } logging.info('Server sending: %r', response) await ws.send_message(json.dumps(response)) except Exception: logging.exception('Server exception') server = await start_server(nursery, handler) async with open_cdp(server) as conn: targets = await conn.execute(target.get_targets()) assert len(targets) == 1 assert isinstance(targets[0], target.TargetInfo)
async def main(): logger.info('Connecting to browser: %s', sys.argv[1]) async with open_cdp(sys.argv[1]) as conn: logger.info('Listing targets') targets = await target.get_targets() for t in targets: if (t.type == 'page' and not t.url.startswith('devtools://') and not t.attached): target_id = t.target_id break logger.info('Attaching to target id=%s', target_id) async with conn.open_session(target_id) as session: logger.info('Setting device emulation') await emulation.set_device_metrics_override( width=800, height=600, device_scale_factor=1, mobile=False ) logger.info('Enabling page events') await page.enable() logger.info('Navigating to %s', sys.argv[2]) async with session.wait_for(page.LoadEventFired): await page.navigate(url=sys.argv[2]) logger.info('Making a screenshot') img_data = await page.capture_screenshot(format='png') logger.info('Saving to file') screenshot_file = await trio.open_file('test.png', 'wb') async with screenshot_file: await screenshot_file.write(b64decode(img_data))
async def main(): logger.info('Connecting to browser: %s', sys.argv[1]) async with open_cdp(sys.argv[1]) as conn: logger.info('Listing targets') targets = await target.get_targets() for t in targets: if (t.type == 'page' and not t.url.startswith('devtools://') and not t.attached): target_id = t.target_id break logger.info('Attaching to target id=%s', target_id) async with conn.open_session(target_id) as session: logger.info('Navigating to %s', sys.argv[2]) await page.enable() async with session.wait_for(page.LoadEventFired): await page.navigate(sys.argv[2]) logger.info('Extracting page title') root_node = await dom.get_document() title_node_id = await dom.query_selector(root_node.node_id, 'title') html = await dom.get_outer_html(title_node_id) print(html)
async def test_session_no_context(nursery, session_handler): ''' Commands should raise an error if called outside of a session context.. ''' server = await start_server(nursery, session_handler) async with open_cdp(server) as conn: with pytest.raises(RuntimeError) as exc_info: node_id = await trio_cdp_dom.query_selector(dom.NodeId(0), 'p.foo') assert str(exc_info.value) == 'dom.query_selector() must be called in a ' \ 'session context.'
async def test_session_context(nursery, session_handler): ''' Open a session context and execute a "simplified" API command in it. ''' server = await start_server(nursery, session_handler) async with open_cdp(server) as conn: async with conn.open_session(target.TargetID('target1')) as session: assert session.session_id == 'session1' node_id = await trio_cdp_dom.query_selector(dom.NodeId(0), 'p.foo') assert node_id == 1
async def save_pdf(browserurl, targeturl, pdfpath, sleeptime): """ make a pdf from a webpage originally https://github.com/HyperionGray/trio-chrome-devtools-protocol/blob/master/examples/screenshot.py Parameters browserurl: str ws address for chrome developer protocol commands targeturl: str url of page to print to pdf pngfile: str filename for png file """ logger.info("Connecting to browser: %s", browserurl) async with open_cdp(browserurl) as conn: logger.info("Listing targets") targets = await conn.execute(target.get_targets()) target_id = targets[0].target_id logger.info("Attaching to target id=%s", target_id) async with conn.open_session(target_id) as session: logger.info("Setting device emulation") await session.execute( emulation.set_device_metrics_override( width=1200, height=2000, device_scale_factor=1, mobile=False ) ) logger.info("Enabling page events") await session.execute(page.enable()) logger.info("Navigating to %s", targeturl) async with session.wait_for(page.LoadEventFired): await session.execute(page.navigate(url=targeturl)) time.sleep(sleeptime) root_node = await session.execute(dom.get_document()) title_node_id = await session.execute( dom.query_selector(root_node.node_id, "body") ) body_html = await session.execute(dom.get_outer_html(title_node_id)) logger.debug(body_html) logger.info("Saving a pdf") # TODO: make sure that javascript finishes rendering # await session.execute(page.capture_screenshot(format="png")) pdf_data, _ = await session.execute(page.print_to_pdf()) pdf_file = await trio.open_file(pdfpath, "wb") async with pdf_file: await pdf_file.write(b64decode(pdf_data)) logger.info(f"wrote {pdfpath}")
async def test_session_execute(nursery, session_handler): ''' Connect a session and execute a command on it. ''' server = await start_server(nursery, session_handler) async with open_cdp(server) as conn: session = await conn.connect_session(target.TargetID('target1')) assert session.session_id == 'session1' node_id = await session.execute( dom.query_selector(dom.NodeId(0), 'p.foo')) assert node_id == 1
async def main(): cdp_uri = sys.argv[1] async with open_cdp(cdp_uri) as conn: logger.info('Connecting') targets = await target.get_targets() target_id = targets[0].target_id # First page logger.info('Attaching to target id=%s', target_id) async with conn.open_session(target_id) as session: logger.info('Started heap snapshot') outfile_path = trio.Path('%s.heapsnapshot' % datetime.today().isoformat()) async with await outfile_path.open('a') as outfile: logger.info('Started writing heap snapshot') await _take_heap_snapshot(session, outfile, report_progress=True)
async def test_listen_for_events(nursery): ''' The server sends 2 different events. The client is listening for a specific type of event and therefore only sees the 2nd one. ''' async def handler(request): # It's tricky to catch exceptions from the server, so exceptions are # logged instead. try: ws = await request.accept() # Send event 1 event = { 'method': 'Page.loadEventFired', 'params': { 'timestamp': 1 }, } logging.info('Server sending: %r', event) await ws.send_message(json.dumps(event)) # Send event 2 event = { 'method': 'Page.loadEventFired', 'params': { 'timestamp': 2 }, } logging.info('Server sending: %r', event) await ws.send_message(json.dumps(event)) except Exception: logging.exception('Server exception') server = await start_server(nursery, handler) async with open_cdp(server) as conn: n = 1 async for event in conn.listen(page.LoadEventFired): assert isinstance(event, page.LoadEventFired) assert event.timestamp == n if n == 2: break n += 1
async def test_wait_for_event(nursery): ''' The server sends 2 different events. The client is listening for a specific type of event and therefore only sees the 2nd one. ''' async def handler(request): # It's tricky to catch exceptions from the server, so exceptions are # logged instead. try: ws = await request.accept() # Send event 1 event = { 'method': 'Page.domContentEventFired', 'params': { 'timestamp': 1 }, } logging.info('Server sending: %r', event) await ws.send_message(json.dumps(event)) # Send event 2 event = { 'method': 'Page.loadEventFired', 'params': { 'timestamp': 2 }, } logging.info('Server sending: %r', event) await ws.send_message(json.dumps(event)) except Exception: logging.exception('Server exception') server = await start_server(nursery, handler) async with open_cdp(server) as conn: async with conn.wait_for(page.LoadEventFired) as event: # In real code we would do something here to trigger a load event, # e.g. clicking a link. pass assert isinstance(event.value, page.LoadEventFired) assert event.value.timestamp == 2
async def test_connection_invalid_json(): ''' If the server sends invalid JSON, that exception is raised on the reader task, which crashes the entire connection. Therefore, the entire test needs to be wrapped in try/except. ''' with pytest.raises(BrowserError) as exc_info: async with trio.open_nursery() as nursery: async def handler(request): # It's tricky to catch exceptions from the server, so exceptions # are logged instead. try: ws = await request.accept() command = json.loads(await ws.get_message()) logging.info('Server received: %r', command) logging.info('Server sending bogus reponse') await ws.send_message('bogus') except Exception: logging.exception('Server exception') server = await start_server(nursery, handler) async with open_cdp(server) as conn: targets = await conn.execute(target.get_targets()) assert exc_info.value.code == -32700 # JSON parse error
async def dom_tree(): # utl вкладки, потом сделать параметром функции и передавать извне target_url = "https://refactoring.guru/ru/design-patterns/python" # подключение к браузеру и поиск вкладок async with open_cdp(ws_url_val()) as conn: targets = await target.get_targets() # в списке всех вкладок ищем вкладку с нужным url target_id = None for t in targets: if t.type_ == 'page' and not t.url.startswith( 'devtools://') and t.url == target_url: target_id = t.target_id # если вкладка не найдена открываем новую с нужным url if not target_id: new_page = await target.create_target(target_url) target_id = new_page # иключение, если вкладка по какой-то причине не открыта или не найдена if not target_id: raise Exception("Указанная вкладка не открыта!") async with conn.open_session(target_id) as session: # Включает агент DOM для данной страницы и дожидаемся полной загрузки вкладки await page.enable() async with session.wait_for(page.LoadEventFired): await page.navigate(target_url) # ПОКА НЕ РАЗОБРАЛСЯ С ОЖИДАНИЕМ ПОЛУЧЕНИЯ ВСЕХ ЭЛЕМЕНТОВ time.sleep(10) root_node6 = await accessibility.get_full_ax_tree() roles_names_coords = [] for i in root_node6: roles_names_coords.append(i.role.value) if i.name: if i.name.value: roles_names_coords.append(i.name.value) else: roles_names_coords.append('NoName') if not i.name: roles_names_coords.append('NoName') # БЛОК ЗНАЧЕНИЙ (МОЖЕТ ПОНАДОБИТСЯ) # if i.name: # if i.name.sources: # if len(i.name.sources) > 2: # if i.name.sources[2].value: # roles_names_coords.append(i.name.sources[2].value.value) # else: # roles_names_coords.append('NoValue') # else: # roles_names_coords.append('NoValue') # if not i.name: # roles_names_coords.append('NoValue') if i.backend_dom_node_id: q = await generated.dom.get_box_model( backend_node_id=i.backend_dom_node_id) roles_names_coords.append( (q.content[0] + q.content[2]) / 2) roles_names_coords.append( (q.content[1] + q.content[5]) / 2) else: roles_names_coords.append('NoCordX') roles_names_coords.append('NoCordY') elements_list = (list(zip(*[iter(roles_names_coords)] * 4))) for element in set(elements_list): if element[0] == 'link': print(element) # TODO - координаты смещаются из-за заголовка chrome if element[1] == 'Go': chrome = Application(backend='uia').connect( title= 'Паттерны проектирования на Python - Google Chrome' ) window_chrome = chrome.window() window_chrome.set_focus() point = tagPOINT(int(element[2]), int(element[3]) + 70) win32api.SetCursorPos((point.x, point.y)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, int(element[2]), int(element[3]), 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, int(element[2]), int(element[3]), 0, 0)