Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > JavaScript, Ajax
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.07.2018, 22:13   #1
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию С помощью JavaScript cохранить изображение на компьютере

Здравствуйте.
Задача такова: есть определённый компонент DOM'a (обнаруженный по XPath, CSS, ClassName или ID - не важно). Заведомо известно, что это элемент img, и у сего компонента есть атрибут src.
Нужно сохранить имеющееся изображение на локальный компьютер в какой нибудь условный путь D:\Images\saving.jpg . Так же заведомо известно, что картинка с сайта поставляется именно в этом формате.

Дальше подробности задачи.

Изначально, мне из элемента с картинкой нужно получить собственно файл картинки, на которой (картинке) изображена капча. Этот файл в дальнейшем держит курс на anti-captcha.com при помощи JSON.
Всё это происходит в моём боте, написанном на C# с использованием Selenium ChromeDriver.
Вот такой вот супчик получился.

Объект ChromeDriver предоставляет возможность сделать скриншот видимой рабочей области окна браузера, но проделать тоже самое с отдельно взятым компонентом возможности нет (гуглил).
Первое что мне пришло в голову - сделать полный скриншот, и по имеющимся координатам компонента вырезать нужную мне область. Но и тут я столкнулся с тем, что скрин у меня только из видимой области, а координаты компонента относительно нуля рабочей области. Компонент с капчей находится почти в самом низу страницы, следовательно, при попытке получить картинку капчи я получаю исключение "переполнение памяти", что на деле означает то, что нужная мне область находится за пределами изображения.

Пока что привязался к нижнему краю страницы, и на 705 пикселе по высоте начинается нужная мне область. Остальные параметры не имеют такой жёсткой привязки. Условно работает, но и тут без JS я не обошёлся:
Код:
driver.ExecuteScript("$('body, html').scrollTop($(document).height());"); // скролл в низ страницы
У такого подхода наблюдаются явные проблемы уже на моём втором мониторе. И это в принципе очевидно было изначально.
Вот я и пришёл сюда узнать, как при помощи того же driver.ExecuteScript выполнить сохранение картинки на компьютер.
Вариант вытянуть картинку прямо из программы (вне ChromeDriver) не рассматривается, ибо по одному и тому же src в разных местах и в разное время я получаю разную капчу (при этом src меняется при каждом обновлении страницы).
Есть ещё вариант попробовать на антикапчу отправлять полный скрин без вырезки, но думаю меня не поймут.
Подпись ? Не, не слышал ...

Последний раз редактировалось OmegaBerkut; 14.07.2018 в 22:49.
OmegaBerkut вне форума Ответить с цитированием
Старый 14.07.2018, 22:31   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Код:
function getImgBase64String(img)
{
    var cnv = document.createElement('CANVAS');
    var ctx = cnv.getContext('2d');
    ctx.drawImage(img, 0, 0);
    return cnv.toDataURL();
}
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.07.2018, 22:37   #3
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Alex11223, куда здесь указывать путь сохранения файла ?
И я не могу понять, где здесь указывать элемент DOM.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 14.07.2018, 22:44   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Никуда, оно base64 вернет.
img это элемент. В Селениуме можно передать в ExecuteScript
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.07.2018, 22:47   #5
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Никуда, оно base64 вернет
И что мне потом с этим base64 делать ? =)
Мне просто нужно в итоге получить файлик возле моего exe-шника ...

UPD: пошёл погуглил, увидел "политику безопасности JS" - типа не имеет доступа к дисковым ресурсам клиента. В принципе, имеет место быть.
Тогда проблема сохранения картинки остаётся открытой. Во всяком случае как делать это наиболее "правильно" и "уверенно" без привязки к другим программным и аппаратным средствам.

Может как то можно в JS организовать массив байтов, и вытянуть его при выполнении driver.ExecuteScript ?
Если с первым пунктом проблем быть не должно, то вот со вторым всё равно вопрос ... Пока что я умею только отправлять данные в JS; как их вытянуть оттуда - большой вопрос.
Подпись ? Не, не слышал ...

Последний раз редактировалось OmegaBerkut; 14.07.2018 в 23:15.
OmegaBerkut вне форума Ответить с цитированием
Старый 14.07.2018, 23:18   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
И что мне потом с этим base64 делать ?
Погуглить что это и конвертировать стандартным методом .NET
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.07.2018, 23:20   #7
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Погуглить что это и конвертировать стандартным методом .NET
Хех ... Этот base64 будет находиться в пределах скрипта. Как его оттуда вытащить в среду .NET ?

Просто сложно гуглить связки различных технологий, в данном случае .NET C# + Selenium WebDriver + JavaScript.

UPD: может можно как то узнать, опять же - в среде C#, какая часть страницы по высоте в пикселях находится выше и/или ниже области видимости ...
Если упростить - то нужно лишь узнать высоту страницы (размеры); размер области видимости у меня есть в виде размеров скриншота. И тогда уже можно будет учесть смещение правильно, а не 705.
Подпись ? Не, не слышал ...

Последний раз редактировалось OmegaBerkut; 14.07.2018 в 23:34.
OmegaBerkut вне форума Ответить с цитированием
Старый 14.07.2018, 23:32   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Код:
 string base64 = (string) WebDriver.ExecuteScript
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.07.2018, 23:42   #9
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Alex11223, хорошо ... А как ранее приведённый вами код выполняет возврат именно нужного результата ?
Ещё раз: гуглить связки, особенно на подобных мелочах - довольно сложно. Везде "общие" решения, либо решения, которые не подходят по тем или иным причинам.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 15.07.2018, 00:21   #10
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Нагуглил что ExecuteScript умеет возвращать различные данные различных типов, и что выполняется анонимная функция; то есть - return data; в скрипте вернёт мне эти самые данные куда мне нужно.
Мою задачу пока что решил так:
Код:
object pageHeight_Obj=driver.ExecuteScript(@"
$('body, html').scrollTop($(document).height()); // проскроллить вниз
return document.body.scrollHeight;"); // получить высоту страницы
int pageHeight=Convert.ToInt32(pageHeight_Obj); // получить число вместо объекта
Дальше вместо 705 поставил
Код:
elem.Location.Y-pageHeight+fullImage.Height
(fullImage это полный скриншот - скриншот области видимости окна браузера)
Вроде как даже работает, и вроде как даже правильно. Уже лучше, но всё равно, привязка к краю области видимости ... Не комильфо.
Пошёл курить base64.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сравнение двух изображение с помощью ImageEn Lorden Общие вопросы Delphi 2 11.06.2015 20:34
Загрузить изображение в вк, с помощью API Rakim4ik Работа с сетью в Delphi 0 19.11.2013 18:07
Javascript изображение Ast JavaScript, Ajax 3 19.12.2011 14:19
Javascript и изображение Ast JavaScript, Ajax 11 18.12.2011 14:24