Exemplo n.º 1
0
 async def evaluateHandle(self,
                          pageFunction: str,
                          *args: Any,
                          force_expr: bool = False) -> 'JSHandle':
     'Execute ``pageFunction`` on this context.\n\n        Details see :meth:`pyppeteer.page.Page.evaluateHandle`.\n        '
     if (force_expr
             or ((not args) and (not helper.is_jsfunc(pageFunction)))):
         _obj = (await self._client.send(
             'Runtime.evaluate', {
                 'expression': pageFunction,
                 'contextId': self._contextId,
                 'returnByValue': False,
                 'awaitPromise': True,
             }))
         exceptionDetails = _obj.get('exceptionDetails')
         if exceptionDetails:
             raise ElementHandleError('Evaluation failed: {}'.format(
                 helper.getExceptionMessage(exceptionDetails)))
         remoteObject = _obj.get('result')
         return self._objectHandleFactory(remoteObject)
     _obj = (await self._client.send(
         'Runtime.callFunctionOn', {
             'functionDeclaration': pageFunction,
             'executionContextId': self._contextId,
             'arguments': [self._convertArgument(arg) for arg in args],
             'returnByValue': False,
             'awaitPromise': True,
         }))
     exceptionDetails = _obj.get('exceptionDetails')
     if exceptionDetails:
         raise ElementHandleError('Evaluation failed: {}'.format(
             helper.getExceptionMessage(exceptionDetails)))
     remoteObject = _obj.get('result')
     return self._objectHandleFactory(remoteObject)
Exemplo n.º 2
0
 def _convertArgument(self, arg: Any) -> Dict:
     if (arg == math.inf):
         return {
             'unserializableValue': 'Infinity',
         }
     if (arg == (-math.inf)):
         return {
             'unserializableValue': '-Infinity',
         }
     objectHandle = (arg if isinstance(arg, JSHandle) else None)
     if objectHandle:
         if (objectHandle._context != self):
             raise ElementHandleError(
                 'JSHandles can be evaluated only in the context they were created!'
             )
         if objectHandle._disposed:
             raise ElementHandleError('JSHandle is disposed!')
         if objectHandle._remoteObject.get('unserializableValue'):
             return {
                 'unserializableValue':
                 objectHandle._remoteObject.get('unserializableValue'),
             }
         if (not objectHandle._remoteObject.get('objectId')):
             return {
                 'value': objectHandle._remoteObject.get('value'),
             }
         return {
             'objectId': objectHandle._remoteObject.get('objectId'),
         }
     return {
         'value': arg,
     }
Exemplo n.º 3
0
    async def evaluateHandle(self, pageFunction: str,
                             *args: Any) -> 'JSHandle':
        """Execute `pageFunction` on this context."""
        if not args and not helper.is_jsfunc(pageFunction):
            _obj = await self._client.send(
                'Runtime.evaluate', {
                    'expression': pageFunction,
                    'contextId': self._contextId,
                    'returnByValue': False,
                    'awaitPromiss': True,
                })
            exceptionDetails = _obj.get('exceptionDetails')
            if exceptionDetails:
                raise ElementHandleError('Evaluation failed: {}'.format(
                    helper.getExceptionMessage(exceptionDetails)))
            remoteObject = _obj.get('result')
            return self._objectHandleFactory(remoteObject)

        _obj = await self._client.send(
            'Runtime.callFunctionOn', {
                'functionDeclaration': pageFunction,
                'executionContextId': self._contextId,
                'arguments': [self._convertArgument(arg) for arg in args],
                'returnByValue': False,
                'awaitPromiss': True,
            })
        exceptionDetails = _obj.get('exceptionDetails')
        if exceptionDetails:
            raise ElementHandleError('Evaluation failed: {}'.format(
                helper.getExceptionMessage(exceptionDetails)))
        remoteObject = _obj.get('result')
        return self._objectHandleFactory(remoteObject)
Exemplo n.º 4
0
    async def _clickablePoint(self) -> Dict[str, float]:  # noqa: C901
        result = None
        try:
            result = await self._client.send(
                'DOM.getContentQuads', {
                    'objectId': self._remoteObject.get('objectId'),
                })
        except Exception as e:
            debugError(logger, e)

        if not result or not result.get('quads'):
            raise ElementHandleError(
                'Node is either not visible or not an HTMLElement')

        quads = []
        for _quad in result.get('quads'):
            _q = self._fromProtocolQuad(_quad)
            if _computeQuadArea(_q) > 1:
                quads.append(_q)
        if not quads:
            raise ElementHandleError(
                'Node is either not visible or not an HTMLElement')

        quad = quads[0]
        x = 0
        y = 0
        for point in quad:
            x += point['x']
            y += point['y']
        return {'x': x / 4, 'y': y / 4}
Exemplo n.º 5
0
 async def evaluateHandle(self,
                          pageFunction: str,
                          *args: Any,
                          force_expr: bool = False) -> 'JSHandle':
     'Execute ``pageFunction`` on this context.\n\n        Details see :meth:`pyppeteer.page.Page.evaluateHandle`.\n        '
     suffix = ''.join(
         ['//# sourceURL=', '{}'.format(EVALUATION_SCRIPT_URL)])
     if (force_expr
             or ((not args) and (not helper.is_jsfunc(pageFunction)))):
         try:
             if SOURCE_URL_REGEX.match(pageFunction):
                 expressionWithSourceUrl = pageFunction
             else:
                 expressionWithSourceUrl = ''.join(
                     ['{}'.format(pageFunction), '\n', '{}'.format(suffix)])
             _obj = (await self._client.send(
                 'Runtime.evaluate', {
                     'expression': expressionWithSourceUrl,
                     'contextId': self._contextId,
                     'returnByValue': False,
                     'awaitPromise': True,
                     'userGesture': True,
                 }))
         except Exception as e:
             _rewriteError(e)
         exceptionDetails = _obj.get('exceptionDetails')
         if exceptionDetails:
             raise ElementHandleError('Evaluation failed: {}'.format(
                 helper.getExceptionMessage(exceptionDetails)))
         remoteObject = _obj.get('result')
         return self._objectHandleFactory(remoteObject)
     try:
         _obj = (await self._client.send(
             'Runtime.callFunctionOn', {
                 'functionDeclaration':
                 ''.join([
                     '{}'.format(pageFunction), '\n', '{}'.format(suffix),
                     '\n'
                 ]),
                 'executionContextId':
                 self._contextId,
                 'arguments': [self._convertArgument(arg) for arg in args],
                 'returnByValue':
                 False,
                 'awaitPromise':
                 True,
                 'userGesture':
                 True,
             }))
     except Exception as e:
         _rewriteError(e)
     exceptionDetails = _obj.get('exceptionDetails')
     if exceptionDetails:
         raise ElementHandleError('Evaluation failed: {}'.format(
             helper.getExceptionMessage(exceptionDetails)))
     remoteObject = _obj.get('result')
     return self._objectHandleFactory(remoteObject)
Exemplo n.º 6
0
    async def screenshot(self, options: Dict = None, **kwargs: Any) -> bytes:
        """Take a screenshot of this element.

        If the element is detached from DOM, this method raises an
        ``ElementHandleError``.

        Available options are same as :meth:`pyppeteer.page.Page.screenshot`.
        """
        options = merge_dict(options, kwargs)

        needsViewportReset = False
        boundingBox = await self.boundingBox()
        if not boundingBox:
            raise ElementHandleError(
                'Node is either not visible or not an HTMLElement')

        original_viewport = copy.deepcopy(self._page.viewport)

        if (boundingBox['width'] > original_viewport['width']
                or boundingBox['height'] > original_viewport['height']):
            newViewport = {
                'width':
                max(original_viewport['width'],
                    math.ceil(boundingBox['width'])),
                'height':
                max(original_viewport['height'],
                    math.ceil(boundingBox['height'])),
            }
            new_viewport = copy.deepcopy(original_viewport)
            new_viewport.update(newViewport)
            await self._page.setViewport(new_viewport)
            needsViewportReset = True

        await self._scrollIntoViewIfNeeded()
        boundingBox = await self.boundingBox()
        if not boundingBox:
            raise ElementHandleError(
                'Node is either not visible or not an HTMLElement')

        _obj = await self._client.send('Page.getLayoutMetrics')
        pageX = _obj['layoutViewport']['pageX']
        pageY = _obj['layoutViewport']['pageY']

        clip = {}
        clip.update(boundingBox)
        clip['x'] = clip['x'] + pageX
        clip['y'] = clip['y'] + pageY
        opt = {'clip': clip}
        opt.update(options)
        imageData = await self._page.screenshot(opt)

        if needsViewportReset:
            await self._page.setViewport(original_viewport)

        return imageData
Exemplo n.º 7
0
    async def evaluateHandle(
            self,
            pageFunction: str,
            *args: Any,  # noqa: C901
            force_expr: bool = False) -> 'JSHandle':
        """Execute ``pageFunction`` on this context.

        Details see :meth:`pyppeteer.page.Page.evaluateHandle`.
        """
        suffix = f'//# sourceURL={EVALUATION_SCRIPT_URL}'

        if force_expr or (not args and not helper.is_jsfunc(pageFunction)):
            try:
                if SOURCE_URL_REGEX.match(pageFunction):
                    expressionWithSourceUrl = pageFunction
                else:
                    expressionWithSourceUrl = f'{pageFunction}\n{suffix}'
                _obj = await self._client.send(
                    'Runtime.evaluate', {
                        'expression': expressionWithSourceUrl,
                        'contextId': self._contextId,
                        'returnByValue': False,
                        'awaitPromise': True,
                        'userGesture': True,
                    })
            except Exception as e:
                _rewriteError(e)

            exceptionDetails = _obj.get('exceptionDetails')
            if exceptionDetails:
                raise ElementHandleError('Evaluation failed: {}'.format(
                    helper.getExceptionMessage(exceptionDetails)))
            remoteObject = _obj.get('result')
            return createJSHandle(self, remoteObject)

        try:
            _obj = await self._client.send(
                'Runtime.callFunctionOn', {
                    'functionDeclaration': f'{pageFunction}\n{suffix}\n',
                    'executionContextId': self._contextId,
                    'arguments': [self._convertArgument(arg) for arg in args],
                    'returnByValue': False,
                    'awaitPromise': True,
                    'userGesture': True,
                })
        except Exception as e:
            _rewriteError(e)

        exceptionDetails = _obj.get('exceptionDetails')
        if exceptionDetails:
            raise ElementHandleError('Evaluation failed: {}'.format(
                helper.getExceptionMessage(exceptionDetails)))
        remoteObject = _obj.get('result')
        return createJSHandle(self, remoteObject)
Exemplo n.º 8
0
 async def queryObjects(self, prototypeHandle: 'JSHandle') -> 'JSHandle':
     'Send query.\n\n        Details see :meth:`pyppeteer.page.Page.queryObjects`.\n        '
     if prototypeHandle._disposed:
         raise ElementHandleError('Prototype JSHandle is disposed!')
     if (not prototypeHandle._remoteObject.get('objectId')):
         raise ElementHandleError(
             'Prototype JSHandle must not be referencing primitive value')
     response = (await self._client.send(
         'Runtime.queryObjects', {
             'prototypeObjectId': prototypeHandle._remoteObject['objectId'],
         }))
     return self._objectHandleFactory(response.get('objects'))
Exemplo n.º 9
0
 async def queryObject(self, prototypeHandle: 'JSHandle') -> 'JSHandle':
     """Send query to the object."""
     if prototypeHandle._disposed:
         raise ElementHandleError('Prototype JSHandle is disposed!')
     if not prototypeHandle._remoteObject.get('objectId'):
         raise ElementHandleError(
             'Prototype JSHandle must not be referencing primitive value')
     response = await self._client.send(
         'Runtime.queryObject', {
             'prototypeObjectId': prototypeHandle._remoteObject['objectId'],
         })
     return self._objectHandleFactory(response.get('objects'))
Exemplo n.º 10
0
 async def addStyleTag(self, options: Dict) -> ElementHandle:
     'Add style tag to this frame.\n\n        Details see :meth:`pyppeteer.page.Page.addStyleTag`.\n        '
     context = (await self.executionContext())
     if (context is None):
         raise ElementHandleError('ExecutionContext is None.')
     addStyleUrl = "\n        async function (url) {\n            const link = document.createElement('link');\n            link.rel = 'stylesheet';\n            link.href = url;\n            const promise = new Promise((res, rej) => {\n                link.onload = res;\n                link.onerror = rej;\n            });\n            document.head.appendChild(link);\n            await promise;\n            return link;\n        }"
     addStyleContent = "\n        async function (content) {\n            const style = document.createElement('style');\n            style.type = 'text/css';\n            style.appendChild(document.createTextNode(content));\n            const promise = new Promise((res, rej) => {\n                style.onload = res;\n                style.onerror = rej;\n            });\n            document.head.appendChild(style);\n            await promise;\n            return style;\n        }"
     if isinstance(options.get('url'), str):
         url = options['url']
         try:
             return (await context.evaluateHandle(addStyleUrl,
                                                  url)).asElement()
         except ElementHandleError as e:
             raise PageError(''.join(
                 ['Loading style from ', '{}'.format(url),
                  ' failed'])) from e
     if isinstance(options.get('path'), str):
         with open(options['path']) as f:
             contents = f.read()
         contents = (
             contents +
             '/*# sourceURL={}*/'.format(options['path'].replace('\n', '')))
         return (await context.evaluateHandle(addStyleContent,
                                              contents)).asElement()
     if isinstance(options.get('content'), str):
         return (await
                 context.evaluateHandle(addStyleContent,
                                        options['content'])).asElement()
     raise ValueError(
         'Provide an object with a `url`, `path` or `content` property')
Exemplo n.º 11
0
 async def _scrollIntoViewIfNeeded(self) -> None:
     error = await self.executionContext.evaluate(
         '''
         async element => {
             if (!element.isConnected)
                 return 'Node is detached from document';
             if (element.nodeType !== Node.ELEMENT_NODE)
                 return 'Node is not of type HTMLElement';
             const visibleRatio = await new Promise(resolve => {
                 const observer = new IntersectionObserver(entries => {
                     resolve(entries[0].intersectionRatio);
                     observer.disconnect();
                 });
                 observer.observe(element);
             });
             if (visibleRatio !== 1.0)
                 element.scrollIntoView({
                     block: 'center',
                     inline: 'center',
                     behavior: 'instant',
                 });
             return false;
         }''', self)
     if error:
         raise ElementHandleError(error)
Exemplo n.º 12
0
    async def querySelectorEval(self, selector: str, pageFunction: str,
                                *args: Any) -> Any:
        """Run ``Page.querySelectorEval`` within the element.

        This method runs ``document.querySelector`` within the element and
        passes it as the first argument to ``pageFunction``. If there is no
        element matching ``selector``, the method raises
        ``ElementHandleError``.

        If ``pageFunction`` returns a promise, then wait for the promise to
        resolve and return its value.

        ``ElementHandle.Jeval`` is a shortcut of this method.

        Example:

        .. code:: python

            tweetHandle = await page.querySelector('.tweet')
            assert (await tweetHandle.querySelectorEval('.like', 'node => node.innerText')) == 100
            assert (await tweetHandle.Jeval('.retweets', 'node => node.innerText')) == 10
        """  # noqa: E501
        elementHandle = await self.querySelector(selector)
        if not elementHandle:
            raise ElementHandleError(
                f'Error: failed to find element matching selector "{selector}"'
            )
        result = await self.executionContext.evaluate(pageFunction,
                                                      elementHandle, *args)
        await elementHandle.dispose()
        return result
Exemplo n.º 13
0
    async def evaluate(self, pageFunction: str, *args: Any) -> Any:
        """[Deprecated] Evaluate the pageFunction on browser."""
        deprecation_msg = (
            'ElementHandle.evaluate is dropped in puppeteer. '
            'Use Page.evaluate(..., ElementHandle) instead.'
        )
        logger.warning('[DEPRECATED] ' + deprecation_msg)
        warnings.warn(deprecation_msg, DeprecationWarning)

        if self._disposed:
            raise ElementHandleError('ElementHandle is disposed!')
        _args = ['this']
        _args.extend(json.dumps(x) for x in args)
        stringifiedArgs = ','.join(_args)
        functionDeclaration = f'''
function() {{ return ({pageFunction})({stringifiedArgs}) }}
'''
        objectId = self._remoteObject.get('objectId')
        obj = await self._client.send(
            'Runtime.callFunctionOn', {
                'objectId': objectId,
                'functionDeclaration': functionDeclaration,
                'returnByValue': False,
                'awaitPromise': True,
            }
        )
        exceptionDetails = obj.get('exceptionDetails', dict())
        remoteObject = obj.get('result', dict())
        if exceptionDetails:
            raise BrowserError(
                'Evaluation failed: ' +
                helper.getExceptionMessage(exceptionDetails)
            )
        return await helper.serializeRemoteObject(self._client, remoteObject)
Exemplo n.º 14
0
 async def addScriptTag(self, options: Dict) -> ElementHandle:
     'Add script tag to this frame.\n\n        Details see :meth:`pyppeteer.page.Page.addScriptTag`.\n        '
     context = (await self.executionContext())
     if (context is None):
         raise ElementHandleError('ExecutionContext is None.')
     addScriptUrl = "\n        async function addScriptUrl(url, type) {\n            const script = document.createElement('script');\n            script.src = url;\n            if (type)\n                script.type = type;\n            const promise = new Promise((res, rej) => {\n                script.onload = res;\n                script.onerror = rej;\n            });\n            document.head.appendChild(script);\n            await promise;\n            return script;\n        }"
     addScriptContent = "\n        function addScriptContent(content, type = 'text/javascript') {\n            const script = document.createElement('script');\n            script.type = type;\n            script.text = content;\n            let error = null;\n            script.onerror = e => error = e;\n            document.head.appendChild(script);\n            if (error)\n                throw error;\n            return script;\n        }"
     if isinstance(options.get('url'), str):
         url = options['url']
         args = [addScriptUrl, url]
         if ('type' in options):
             args.append(options['type'])
         try:
             return (await context.evaluateHandle(*args)).asElement()
         except ElementHandleError as e:
             raise PageError(''.join(
                 ['Loading script from ', '{}'.format(url),
                  ' failed'])) from e
     if isinstance(options.get('path'), str):
         with open(options['path']) as f:
             contents = f.read()
         contents = (
             contents +
             '//# sourceURL={}'.format(options['path'].replace('\n', '')))
         args = [addScriptContent, contents]
         if ('type' in options):
             args.append(options['type'])
         return (await context.evaluateHandle(*args)).asElement()
     if isinstance(options.get('content'), str):
         args = [addScriptContent, options['content']]
         if ('type' in options):
             args.append(options['type'])
         return (await context.evaluateHandle(*args)).asElement()
     raise ValueError(
         'Provide an object with a `url`, `path` or `content` property')
Exemplo n.º 15
0
 def executionContextById(self, contextId: str) -> ExecutionContext:
     """Get stored ``ExecutionContext`` by ``id``."""
     context = self._contextIdToContext.get(contextId)
     if not context:
         raise ElementHandleError(
             f'INTERNAL ERROR: missing context with id = {contextId}')
     return context
    async def addStyleTag(self, options: Dict) -> ElementHandle:
        """Add style tag to this frame.

        Details see :meth:`pyppeteer.page.Page.addStyleTag`.
        """
        context = await self.executionContext()
        if context is None:
            raise ElementHandleError('ExecutionContext is None.')

        addStyleUrl = '''
        async function (url) {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = url;
            const promise = new Promise((res, rej) => {
                link.onload = res;
                link.onerror = rej;
            });
            document.head.appendChild(link);
            await promise;
            return link;
        }'''

        addStyleContent = '''
        async function (content) {
            const style = document.createElement('style');
            style.type = 'text/css';
            style.appendChild(document.createTextNode(content));
            const promise = new Promise((res, rej) => {
                style.onload = res;
                style.onerror = rej;
            });
            document.head.appendChild(style);
            await promise;
            return style;
        }'''

        if isinstance(options.get('url'), str):
            url = options['url']
            try:
                return (await context.evaluateHandle(  # type: ignore
                    addStyleUrl, url)).asElement()
            except ElementHandleError as e:
                raise PageError(f'Loading style from {url} failed') from e

        if isinstance(options.get('path'), str):
            with open(options['path']) as f:
                contents = f.read()
            contents = contents + '/*# sourceURL={}*/'.format(
                options['path'].replace('\n', ''))
            return (await context.evaluateHandle(  # type: ignore
                addStyleContent, contents)).asElement()

        if isinstance(options.get('content'), str):
            return (await context.evaluateHandle(  # type: ignore
                addStyleContent, options['content'])).asElement()

        raise ValueError(
            'Provide an object with a `url`, `path` or `content` property')
 def _convertArgument(self, arg: Any) -> Dict:  # noqa: C901
     if arg == math.inf:
         return {'unserializableValue': 'Infinity'}
     if arg == -math.inf:
         return {'unserializableValue': '-Infinity'}
     objectHandle = arg if isinstance(arg, JSHandle) else None
     if objectHandle:
         if objectHandle._context != self:
             raise ElementHandleError('JSHandles can be evaluated only in the context they were created!')  # noqa: E501
         if objectHandle._disposed:
             raise ElementHandleError('JSHandle is disposed!')
         if objectHandle._remoteObject.get('unserializableValue'):
             return {'unserializableValue': objectHandle._remoteObject.get('unserializableValue')}  # noqa: E501
         if not objectHandle._remoteObject.get('objectId'):
             return {'value': objectHandle._remoteObject.get('value')}
         return {'objectId': objectHandle._remoteObject.get('objectId')}
     return {'value': arg}
Exemplo n.º 18
0
def valueFromRemoteObject(remoteObject: Dict) -> Any:
    'Serialize value of remote object.'
    if remoteObject.get('objectId'):
        raise ElementHandleError('Cannot extract value when objectId is given')
    value = remoteObject.get('unserializableValue')
    if value:
        if (value == '-0'):
            return (- 0)
        elif (value == 'NaN'):
            return None
        elif (value == 'Infinity'):
            return math.inf
        elif (value == '-Infinity'):
            return (- math.inf)
        else:
            raise ElementHandleError(
                'Unsupported unserializable value: {}'.format(value))
    return remoteObject.get('value')
Exemplo n.º 19
0
 async def _visibleCenter(self) -> Dict[str, float]:
     await self._scrollIntoViewIfNeeded()
     box = await self.boundingBox()
     if not box:
         raise ElementHandleError('Node is not visible.')
     return {
         'x': box['x'] + box['width'] / 2,
         'y': box['y'] + box['height'] / 2,
     }
Exemplo n.º 20
0
 def createJSHandle(self,
                    contextId: str,
                    remoteObject: Dict = None) -> JSHandle:
     """Create JS handle associated to the context id and remote object."""
     if remoteObject is None:
         remoteObject = dict()
     context = self._contextIdToContext.get(contextId)
     if not context:
         raise ElementHandleError(f'missing context with id = {contextId}')
     return createJSHandle(context, remoteObject)
Exemplo n.º 21
0
    async def evaluate(self, pageFunction: str, *args: Any,
                       force_expr: bool = False) -> Any:
        """Evaluate pageFunction on this frame.

        Details see :meth:`pyppeteer.page.Page.evaluate`.
        """
        context = await self.executionContext()
        if context is None:
            raise ElementHandleError('ExecutionContext is None.')
        return await context.evaluate(
            pageFunction, *args, force_expr=force_expr)
Exemplo n.º 22
0
 async def querySelectorAllEval(self, selector: str, pageFunction: str,
                                *args: Any) -> Optional[Dict]:
     """Execute function on all elements which matches selector."""
     if self._context is None:
         raise ElementHandleError('ExecutionContext is None.')
     arrayHandle = await self._context.evaluateHandle(
         'selector => Array.from(document.querySelectorAll(selector))',
         selector,
     )
     result = await self.evaluate(pageFunction, arrayHandle, *args)
     await arrayHandle.dispose()
     return result
Exemplo n.º 23
0
 def createJSHandle(self, contextId: str, remoteObject: Dict = None
                    ) -> 'JSHandle':
     """Create JS handle associated to the context id and remote object."""
     if remoteObject is None:
         remoteObject = dict()
     context = self._contextIdToContext.get(contextId)
     if not context:
         raise ElementHandleError(f'missing context with id = {contextId}')
     if remoteObject.get('subtype') == 'node':
         return ElementHandle(context, self._client, remoteObject,
                              self._page)
     return JSHandle(context, self._client, remoteObject)
Exemplo n.º 24
0
 async def querySelectorAllEval(self, selector: str, pageFunction: str,
                                *args: Any) -> Optional[Dict]:
     'Execute function on all elements which matches selector.\n\n        Details see :meth:`pyppeteer.page.Page.querySelectorAllEval`.\n        '
     context = (await self.executionContext())
     if (context is None):
         raise ElementHandleError('ExecutionContext is None.')
     arrayHandle = (await context.evaluateHandle(
         'selector => Array.from(document.querySelectorAll(selector))',
         selector))
     result = (await self.evaluate(pageFunction, arrayHandle, *args))
     (await arrayHandle.dispose())
     return result
Exemplo n.º 25
0
 async def _scrollIntoViewIfNeeded(self) -> None:
     error = await self.executionContext.evaluate(
         '''element => {
             if (!element.ownerDocument.contains(element))
                 return 'Node is detached from document';
             if (element.nodeType !== Node.ELEMENT_NODE)
                 return 'Node is not of type HTMLElement';
             element.scrollIntoViewIfNeeded();
             return false;
         }''', self)
     if error:
         raise ElementHandleError(error)
Exemplo n.º 26
0
    async def addScriptTag(self, options: Dict) -> ElementHandle:
        """Add script tag to this frame.

        Details see :meth:`pyppeteer.page.Page.addScriptTag`.
        """
        context = await self.executionContext()
        if context is None:
            raise ElementHandleError('ExecutionContext is None.')

        addScriptUrl = '''
        async function addScriptUrl(url) {
            const script = document.createElement('script');
            script.src = url;
            document.head.appendChild(script);
            await new Promise((res, rej) => {
                script.onload = res;
                script.onerror = rej;
            });
            return script;
        }'''

        addScriptContent = '''
        function addScriptContent(content) {
            const script = document.createElement('script');
            script.type = 'text/javascript';
            script.text = content;
            document.head.appendChild(script);
            return script;
        }'''

        if isinstance(options.get('url'), str):
            url = options['url']
            try:
                return (await context.evaluateHandle(  # type: ignore
                    addScriptUrl, url)).asElement()
            except ElementHandleError as e:
                raise PageError(f'Loading script from {url} failed') from e

        if isinstance(options.get('path'), str):
            with open(options['path']) as f:
                contents = f.read()
            contents = contents + '//# sourceURL={}'.format(
                options['path'].replace('\n', ''))
            return (await context.evaluateHandle(  # type: ignore
                addScriptContent, contents)).asElement()

        if isinstance(options.get('content'), str):
            return (await context.evaluateHandle(  # type: ignore
                addScriptContent, options['content'])).asElement()

        raise ValueError(
            'Provide an object with a `url`, `path` or `content` property')
Exemplo n.º 27
0
 async def querySelectorEval(self, selector: str, pageFunction: str,
                             *args: Any) -> Any:
     "Run ``Page.querySelectorEval`` within the element.\n\n        This method runs ``document.querySelector`` within the element and\n        passes it as the first argument to ``pageFunction``. If there is no\n        element matching ``selector``, the method raises\n        ``ElementHandleError``.\n\n        If ``pageFunction`` returns a promise, then wait for the promise to\n        resolve and return its value.\n\n        ``ElementHandle.Jeval`` is a shortcut of this method.\n\n        Example:\n\n        .. code:: python\n\n            tweetHandle = await page.querySelector('.tweet')\n            assert (await tweetHandle.querySelectorEval('.like', 'node => node.innerText')) == 100\n            assert (await tweetHandle.Jeval('.retweets', 'node => node.innerText')) == 10\n        "
     elementHandle = (await self.querySelector(selector))
     if (not elementHandle):
         raise ElementHandleError(''.join([
             'Error: failed to find element matching selector "',
             '{}'.format(selector), '"'
         ]))
     result = (await self.executionContext.evaluate(pageFunction,
                                                    elementHandle, *args))
     (await elementHandle.dispose())
     return result
Exemplo n.º 28
0
    async def querySelector(self, selector: str) -> Optional[ElementHandle]:
        """Get element which matches `selector` string.

        Details see :meth:`pyppeteer.page.Page.querySelector`.
        """
        if self._context is None:
            raise ElementHandleError('ExecutionContext is None.')
        handle = await self._context.evaluateHandle(
            'selector => document.querySelector(selector)', selector)
        element = handle.asElement()
        if element:
            return element
        await handle.dispose()
        return None
Exemplo n.º 29
0
    async def querySelector(self, selector: str) -> Optional[ElementHandle]:
        """Get element which matches `selector` string.

        If `selector` matches multiple elements, return first-matched element.
        """
        if self._context is None:
            raise ElementHandleError('ExecutionContext is None.')
        handle = await self._context.evaluateHandle(
            'selector => document.querySelector(selector)', selector)
        element = handle.asElement()
        if element:
            return element
        await handle.dispose()
        return None
Exemplo n.º 30
0
 def createJSHandle(self,
                    contextId: str,
                    remoteObject: Dict = None) -> JSHandle:
     'Create JS handle associated to the context id and remote object.'
     if (remoteObject is None):
         remoteObject = dict()
     context = self._contextIdToContext.get(contextId)
     if (not context):
         raise ElementHandleError(''.join(
             ['missing context with id = ', '{}'.format(contextId)]))
     if (remoteObject.get('subtype') == 'node'):
         return ElementHandle(context, self._client, remoteObject,
                              self._page, self)
     return JSHandle(context, self._client, remoteObject)