Download image with selenium python
Here's a complete example (using google's recaptcha as a target):
import urllibfrom selenium import webdriverdriver = webdriver.Firefox()driver.get('http://www.google.com/recaptcha/demo/recaptcha')# get the image sourceimg = driver.find_element_by_xpath('//div[@id="recaptcha_image"]/img')src = img.get_attribute('src')# download the imageurllib.urlretrieve(src, "captcha.png")driver.close()
UPDATE:
The problem with dynamic generated images is that there is a new image generated each time you request it. In that case, you have several options:
take a screenshot
from selenium import webdriverdriver = webdriver.Firefox()driver.get('https://moscowsg.megafon.ru/ps/scc/php/cryptographp.php?PHPSESSID=mfc540jkbeme81qjvh5t0v0bnjdr7oc6&ref=114&w=150')driver.save_screenshot("screenshot.png")driver.close()
simulate right click + "Save As". See this thread for more info.
Hope that helps.
It's ok to save a screenshot from the whole page and then cut the image from, but you can also to use the "find" method from "webdriver" to locate the image you want to save, and write the "screenshot_as_png" property like below:
from selenium import webdriverdriver = webdriver.Firefox()driver.get('https://www.webpagetest.org/')with open('filename.png', 'wb') as file: file.write(driver.find_element_by_xpath('/html/body/div[1]/div[5]/div[2]/table[1]/tbody/tr/td[1]/a/div').screenshot_as_png)
Sometimes it could get an error because of the scroll, but depending on your necessity, it's a good way to get the image.
The problem of using save_screenshot
is that we cannot save an image in its original quality and cannot restore the alpha channel in an image. Therefore, I propose another solution. Here is a complete example using the selenium-wire
library suggested by @codam_hsmits. It is possible to download images via ChromeDriver
.
I have defined the following function to parse each request and save the request body to a file when necessary.
from seleniumwire import webdriver # Import from seleniumwirefrom urllib.parse import urlparseimport osfrom mimetypes import guess_extensionimport timeimport datetimedef download_assets(requests, asset_dir="temp", default_fname="unnamed", skip_domains=["facebook", "google", "yahoo", "agkn", "2mdn"], exts=[".png", ".jpeg", ".jpg", ".svg", ".gif", ".pdf", ".bmp", ".webp", ".ico"], append_ext=False): asset_list = {} for req_idx, request in enumerate(requests): # request.headers # request.response.body is the raw response body in bytes if request is None or request.response is None or request.response.headers is None or 'Content-Type' not in request.response.headers: continue ext = guess_extension(request.response.headers['Content-Type'].split(';')[0].strip()) if ext is None or ext == "" or ext not in exts: #Don't know the file extention, or not in the whitelist continue parsed_url = urlparse(request.url) skip = False for d in skip_domains: if d in parsed_url.netloc: skip = True break if skip: continue frelpath = parsed_url.path.strip() if frelpath == "": timestamp = str(datetime.datetime.now().replace(microsecond=0).isoformat()) frelpath = f"{default_fname}_{req_idx}_{timestamp}{ext}" elif frelpath.endswith("\\") or frelpath.endswith("/"): timestamp = str(datetime.datetime.now().replace(microsecond=0).isoformat()) frelpath = frelpath + f"{default_fname}_{req_idx}_{timestamp}{ext}" elif append_ext and not frelpath.endswith(ext): frelpath = frelpath + f"_{default_fname}{ext}" #Missing file extension but may not be a problem if frelpath.startswith("\\") or frelpath.startswith("/"): frelpath = frelpath[1:] fpath = os.path.join(asset_dir, parsed_url.netloc, frelpath) if os.path.isfile(fpath): continue os.makedirs(os.path.dirname(fpath), exist_ok=True) print(f"Downloading {request.url} to {fpath}") asset_list[fpath] = request.url try: with open(fpath, "wb") as file: file.write(request.response.body) except: print(f"Cannot download {request.url} to {fpath}") return asset_list
Let's download some images from Google homepage to temp
folder.
# Create a new instance of the Chrome/Firefox driverdriver = webdriver.Chrome()# Go to the Google home pagedriver.get('https://www.google.com')# Download content to temp folderasset_dir = "temp"while True: # Please browser the internet, it will collect the images for every second time.sleep(1) download_assets(driver.requests, asset_dir=asset_dir)driver.close()
Note that it cannot decide which images can be seen on the page rather than being hidden in the background, so the users should actively click the buttons or links to trigger new download requests.