Esempio n. 1
0
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))
Esempio n. 2
0
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
Esempio n. 3
0
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)
Esempio n. 4
0
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)
Esempio n. 6
0
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.'
Esempio n. 7
0
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
Esempio n. 8
0
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}")
Esempio n. 9
0
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
Esempio n. 10
0
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)
Esempio n. 11
0
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
Esempio n. 12
0
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
Esempio n. 13
0
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
Esempio n. 14
0
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)