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

182
10 апреля 2019, 13:00

Есть ссылка на сайт. Необходимо получить 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 не предлагать. Не справляется.

Answer 1

Код тут :

https://github.com/Zimtir/NodeScreenshoter/

Оф. документация тут :

https://github.com/GoogleChrome/puppeteer/blob/v1.10.0/docs/api.md#elementhandlescreenshotoptions

Answer 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 раз, а дальше просто перебирать координаты и размеры нужных нод.

READ ALSO
Какую использовать базу данных для “windows form”? [закрыт]

Какую использовать базу данных для “windows form”? [закрыт]

Приложение устанавливаться не будетНужна небольшая бд

168
get запрос через прокси c#

get запрос через прокси c#

Как отправить get запрос на определенный урл через прокси? Результат обрабатывать никак не надо, необходимо просто обратится к апи сервиса...

182
Как сделать привязку x:Bind StackPanel к GridView

Как сделать привязку x:Bind StackPanel к GridView

GridView отображает на странице данные из коллекции объектов:

182