Мне было интересно, как можно использовать selenium/webdriver для загрузки изображения для страницы. Предполагая, что сеанс пользователя необходим для загрузки изображения, поэтому наличие чистого URL-адреса не является полезным. Любой пример кода высоко ценится.
Как загрузить изображение с помощью Selenium (любая версия)?
Ответ 1
Я предпочитаю делать что-то вроде этого:
1. Get the SRC attribute of the image.
2. Use ImageIO.read to read the image onto a BufferedImage
3. Save the BufferedImage using ImageIO.write function
Например,
String src = imgElement.getAttribute('src');
BufferedImage bufferedImage = ImageIO.read(new URL(src));
File outputfile = new File("saved.png");
ImageIO.write(bufferedImage, "png", outputfile);
Ответ 2
Другим вариантом будет симуляция правого клика и использование контекстного меню здесь
Ответ 3
Я предпочитаю вот так:
WebElement logo = driver.findElement(By.cssSelector(".image-logo"));
String logoSRC = logo.getAttribute("src");
URL imageURL = new URL(logoSRC);
BufferedImage saveImage = ImageIO.read(imageURL);
ImageIO.write(saveImage, "png", new File("logo-image.png"));
Ответ 4
Другим в основном правильным решением является загрузка его напрямую с помощью простого HTTP-запроса.
Вы можете использовать сеанс пользователя webDriver, чтобы он хранил файлы cookie.
В моем примере я просто анализирую, какой код состояния он возвращает. Если 200, то изображение существует, и оно доступно для показа или загрузки. Если вам действительно нужно загрузить файл, вы можете просто получить все данные изображения из объекта httpResponse (использовать его как простой поток ввода).
// just look at your cookie content (e.g. using browser)
// and import these settings from it
private static final String SESSION_COOKIE_NAME = "JSESSIONID";
private static final String DOMAIN = "domain.here.com";
private static final String COOKIE_PATH = "/cookie/path/here";
protected boolean isResourceAvailableByUrl(String resourceUrl) {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
BasicCookieStore cookieStore = new BasicCookieStore();
// apply jsessionid cookie if it exists
cookieStore.addCookie(getSessionCookie());
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
// resourceUrl - is url which leads to image
HttpGet httpGet = new HttpGet(resourceUrl);
try {
HttpResponse httpResponse = httpClient.execute(httpGet, localContext);
return httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
} catch (IOException e) {
return false;
}
}
protected BasicClientCookie getSessionCookie() {
Cookie originalCookie = webDriver.manage().getCookieNamed(SESSION_COOKIE_NAME);
if (originalCookie == null) {
return null;
}
// just build new apache-like cookie based on webDriver one
String cookieName = originalCookie.getName();
String cookieValue = originalCookie.getValue();
BasicClientCookie resultCookie = new BasicClientCookie(cookieName, cookieValue);
resultCookie.setDomain(DOMAIN);
resultCookie.setExpiryDate(originalCookie.getExpiry());
resultCookie.setPath(COOKIE_PATH);
return resultCookie;
}
Ответ 5
Другие решения здесь не работают во всех браузерах, не работают на всех веб-сайтах или и то, и другое.
Это решение должно быть гораздо более надежным. Он использует браузер для просмотра изображения, изменяет размер браузера в соответствии с размером изображения, снимает скриншот и, наконец, изменяет размер браузера на исходный размер.
Python:
def get_image(driver, img_url):
'''Given an images url, return a binary screenshot of it in png format.'''
driver.get_url(img_url)
# Get the dimensions of the browser and image.
orig_h = driver.execute_script("return window.outerHeight")
orig_w = driver.execute_script("return window.outerWidth")
margin_h = orig_h - driver.execute_script("return window.innerHeight")
margin_w = orig_w - driver.execute_script("return window.innerWidth")
new_h = driver.execute_script('return document.getElementsByTagName("img")[0].height')
new_w = driver.execute_script('return document.getElementsByTagName("img")[0].width')
# Resize the browser window.
logging.info("Getting Image: orig %sX%s, marg %sX%s, img %sX%s - %s"%(
orig_w, orig_h, margin_w, margin_h, new_w, new_h, img_url))
driver.set_window_size(new_w + margin_w, new_h + margin_h)
# Get the image by taking a screenshot of the page.
img_val = driver.get_screenshot_as_png()
# Set the window size back to what it was.
driver.set_window_size(orig_w, orig_h)
# Go back to where we started.
driver.back()
return img_val
Одним из недостатков этого решения является то, что если изображение очень малое, браузер не будет изменять размер этого маленького размера, и вы можете получить черную рамку вокруг него.
Ответ 6
использовать селен для получения изображения src
elemImg.get_attribute('src')
используйте для этого язык программирования для python; проверьте этот ответ: Как сохранить изображение локально с помощью Python, адрес URL которого я уже знаю?
Ответ 7
Если вам нужно проверить, что изображение доступно и существует, вы можете сделать следующее:
protected boolean isResourceAvailableByUrl(String resourceUrl) {
// backup current url, to come back to it in future
String currentUrl = webDriver.getCurrentUrl();
try {
// try to get image by url
webDriver.get(resourceUrl);
// if "resource not found" message was not appeared - image exists
return webDriver.findElements(RESOURCE_NOT_FOUND).isEmpty();
} finally {
// back to page
webDriver.get(currentUrl);
}
}
Но вы должны быть уверены, что через currentUrl действительно вернется на страницу перед выполнением этого метода. В моем случае это было так. Если нет - вы можете попробовать:
webDriver.navigate().back()
А также, к сожалению, как кажется, нет никакой возможности проанализировать код статуса ответа. Вот почему вам нужно найти какой-либо конкретный веб-элемент на странице NOT_FOUND и проверить, что он появился и решить тогда - это изображение не существует.
Это просто обходной путь, потому что я не нашел никакого официального способа его решения.
Примечание: Это решение полезно в том случае, если вы используете авторизованный сеанс для получения ресурса и не можете просто загрузить его с помощью ImageIO или строго HttpClient.
Ответ 8
вот решение javascript. это немного глупо - и я устал от попадания на сервер исходного изображения со слишком большим количеством запросов. может кто-нибудь сказать мне, если fetch() обращается к кешу браузера? я не хочу спамить исходный сервер.
он добавляет FileReader() к окну, извлекает и преобразует изображение в base64 и отмечает эту строку в окне.
Затем драйвер может вернуть эту переменную окна.
export async function scrapePic(driver) {
try {
console.log("waiting for that profile piccah")
console.log(driver)
let rootEl = await driver.findElement(By.css('.your-root-element'));
let imgEl = await rootEl.findElement(By.css('img'))
await driver.wait(until.elementIsVisible(imgEl, 10000));
console.log('profile piccah found')
let img = await imgEl.getAttribute('src')
//attach reader to driver window
await driver.executeScript('window.myFileReader = new FileReader();')
await driver.executeScript('
window.myFileReader.onloadend = function() {
window['profileImage'] = this.result
}
fetch( arguments[0] ).then( res => res.blob() ).then( blob => window.electronFileReader.readAsDataURL(blob) )
', img)
await driver.sleep(5000)
let img64 = await driver.executeScript('return window.profileImage')
console.log(img64)
} catch (e) {
console.log(e)
} finally {
return img64
}
}
Ответ 9
Работает для меня:
# open the image in a new tab
driver.execute_script('''window.open("''' + wanted_url + '''","_blank");''')
sleep(2)
driver.switch_to.window(driver.window_handles[1])
sleep(2)
# make screenshot
driver.save_screenshot("C://Folder/" + photo_name + ".jpeg")
sleep(2)
# close the new tab
driver.execute_script('''window.close();''')
sleep(2)
#back to original tab
driver.switch_to.window(driver.window_handles[0])
Ответ 10
Для моего варианта использования были файлы cookie и другие проблемы, которые делали другие подходы здесь непригодными.
Я закончил тем, что использовал XMLHttpRequest для заполнения FileReader (из Как преобразовать изображение в строку base64 с помощью javascript, а затем вызвал его с помощью Selenium ExecuteAsyncScript
(как показано в Selenium и асинхронных вызовах JavaScript <)). Это позволило мне получить URL-адрес данных, который можно было легко проанализировать.
Вот мой код С# для получения URL-адреса данных:
public string ImageUrlToDataUrl(IWebDriver driver, string imageUrl)
{
var js = new StringBuilder();
js.AppendLine("var done = arguments[0];"); // The callback from ExecuteAsyncScript
js.AppendLine(@"
function toDataURL(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}"); // XMLHttpRequest -> FileReader -> DataURL conversion
js.AppendLine("toDataURL('" + imageUrl + "', done);"); // Invoke the function
var executor = (IJavaScriptExecutor) driver;
var dataUrl = executor.ExecuteAsyncScript(js.ToString()) as string;
return dataUrl;
}