Comment télécharger une image avec Selenium (n'importe quelle version)?

je me demandais comment utiliser selenium/webdriver pour télécharger une image pour une page. En supposant que la session de l'utilisateur est nécessaire pour télécharger l'image par conséquent ayant L'URL pure n'est pas utile. Tout exemple de code est très apprécié.

19
demandé sur Ali Salehi 2011-07-25 12:56:08

8 réponses

je préfère faire quelque chose comme ceci :

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
14
répondu coding_idiot 2012-11-08 13:18:02

Ici est un truc qui fonctionne dans Firefox et Chrome, fait essentiellement du sélénium pour ouvrir un nouveau navigateur juste avec l'image et ensuite le télécharge avec Ctrl+S.

une Autre option serait de simuler le clic droit et utilisez le menu contextuel ici

10
répondu jasalguero 2017-05-23 12:10:47

je préfère comme ceci:

 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"));
3
répondu samson 2017-04-26 17:46:48

une autre solution plutôt correcte est de le télécharger directement par simple requête HTTP.

Vous pouvez utiliser la session utilisateur de webDriver, car il stocke des cookies.

Dans mon exemple, j'analyse juste le code de statut qu'il renvoie. Si 200, puis l'image existe et il est disponible pour afficher ou télécharger. Si vous avez vraiment besoin de télécharger le fichier lui - même-vous pouvez juste obtenir toutes les données d'image de l'entité httpResponse (utilisez-le comme flux d'entrée simple).

// just look at your cookie's 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's 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;
}
2
répondu Gadget 2013-02-20 18:18:04

si vous avez besoin de tester que l'image est disponible et existe, Vous pouvez faire comme ceci:

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);
    }
}

mais vous devez être sûr, qu'en passant par currentUrl vous retournerez vraiment sur la page avant l'exécution de cette méthode. Dans mon cas, c'était ainsi. Sinon, vous pouvez essayer d'utiliser:

webDriver.navigate().back()

Et aussi, malheureusement, comme il semble, il n'y a aucune chance pour analyser le code d'état de réponse. C'est pourquoi vous devez trouver tout élément web spécifique sur NOT_FOUND page et vérifier qu'il était apparu et décider alors - que l'image n'existe pas.

c'est juste un contournement, parce que je n'ai trouvé aucun moyen officiel de le résoudre.

NOTE: Cette solution est utile dans le cas où vous utilisez session autorisée pour obtenir la ressource, et ne peut pas simplement la télécharger par ImageIO ou strictement par HttpClient.

0
répondu Gadget 2013-01-18 16:54:57

utiliser le sélénium pour obtenir l'image src

elemImg.get_attribute('src')

Utilisez le langage de programmation pour cela, pour python; cochez cette réponse: comment sauvegarder une image localement en utilisant Python dont je connais déjà l'adresse URL?

0
répondu Bassem Shahin 2017-05-23 05:51:07

d'Autres solutions ne fonctionnent pas sur tous les navigateurs, ne fonctionnent pas sur tous les sites, ou les deux.

Cette solution devrait être beaucoup plus robuste. Il utilise le navigateur pour afficher l'image, redimensionne le navigateur pour s'adapter à la taille de l'image, prend une capture d'écran, et enfin redimensionne le navigateur vers le format de l'original.

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

un inconvénient de cette solution est que si l'image est très petite, le navigateur ne redimensionnera pas cette petite, et vous pouvez obtenir une bordure noire autour de lui.

0
répondu speedplane 2017-07-07 01:16:07

voici une solution javascript. c'est un peu stupide ... et je suis lasse de frapper le serveur de l'image source avec trop de requêtes. quelqu'un peut-il me dire si le fetch() accède au cache du navigateur? Je ne veux pas spam le serveur source.

il ajoute un FileReader () à la fenêtre, récupère et convertit l'image en base64 et marque cette chaîne sur la fenêtre.

le pilote peut alors retourner cette fenêtre variable.

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
  }
}
0
répondu nacmonad 2018-08-01 16:31:02