Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

Скриншот всех nodes

#javascript #c_sharp #net #nodejs #веб_программирование


Есть ссылка на сайт.
Необходимо получить selector или xpath для всех доступных элементов.

К примеру, есть https://youtube.com
Если мы возьмем элемент по

//*[@id="meta"]/h3


То мы получим какой-либо объект и сможем например вызвать у него 

getBoundingClientRect()


Тоже самое если брать селектор элемента 

#meta > h3


По нему всё тоже нормально

Потому что элемент видим.

Как решить эту задачу?

Единственный вариант к которому пришел - это поднимать CefSharp и бегать через keyboard
control по Nodes в DevTools и получать xPath/selector нажатием правой кнопки мыши

Что пробовал :

HtmlAgilityPack (C#) подключался через web.load("youtube.com") и кормил его HtmlDocument
Но я получал NodeCollection, где xPath /html[1]/body[1]/div[1]

Почему такой вариант не подходит?

puppeteer не может сделать скриншот на основе этого элемента, не знаю почему, но
не может.

реализация нужна именно под puppeteer (он лучше всего справляется с созданием скриншота
на основе xpath/selector)

async function screenshotDOMElement(opts = {}) {
    const padding = 'padding' in opts ? opts.padding : 0;
    const path = 'path' in opts ? opts.path : null;
    const selector = opts.selector;

    if (!selector)
        throw Error('Please provide a selector.');

    const rect = await page.evaluate(selector => {
        const element =
         document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE,
null).singleNodeValue;
        if (!element)
            return null;
        const {x, y, width, height} = element.getBoundingClientRect();
        console.log (x,y,width,height)
        return {left: x, top: y, width, height, id: element.id};
    }, selector);

    if (!rect)
        throw Error(`Could not find element that matches selector: ${selector}.`);

    return await page.screenshot({
        path,
        clip: {
            x: rect.left - padding,
            y: rect.top - padding,
            width: rect.width + padding * 2,
            height: rect.height + padding * 2
        }
    });
}


Как получить скриншот всех элементов какого-либо сайта?

Selenium не предлагать. Не справляется.
    


Ответы

Ответ 1



Код тут : https://github.com/Zimtir/NodeScreenshoter/ Оф. документация тут : https://github.com/GoogleChrome/puppeteer/blob/v1.10.0/docs/api.md#elementhandlescreenshotoptions

Ответ 2



Через селениум: Сначала находим в нужной ноды размер и позицию: Size elemSize = Element.Size; Point point = Element.Location; Потом берем скриншот стандартными средствами селениума и обрезаем по уже снятых ранее параметрах Screenshot myScreenShot = ((ITakesScreenshot)Instance).GetScreenshot(); Bitmap screen = new Bitmap(new MemoryStream(myScreenShot.AsByteArray)); Bitmap nodeScreen = screen.Clone(new Rectangle(point, size), screen.PixelFormat); Собственно, дальше остается только сделать перебор всех нод и сделать скриншот. PhantomJS, на сколько я помню, делает скриншот ВСЕЙ страницы какого бы размера оне не была. Так что никаких костылей связанных с тем, что элемент не видно на странице не будет в случае его использования. Так же для оптимизации можно делать скриншот страницы только 1 раз, а дальше просто перебирать координаты и размеры нужных нод.

Комментариев нет:

Отправить комментарий