【问题标题】:Selenium downloading different captcha image than the one in browserSelenium 下载与浏览器中不同的验证码图像
【发布时间】:2016-08-06 18:48:28
【问题描述】:

我正在尝试使用 Selenium 下载验证码图像,但是,我下载的图像与浏览器中显示的图像不同。 如果我尝试再次下载图像,而不更改浏览器,我会得到一个不同的。

有什么想法吗?

from selenium import webdriver
import urllib


driver = webdriver.Firefox()
driver.get("http://sistemas.cvm.gov.br/?fundosreg")

# Change frame.
driver.switch_to.frame("Main")


# Download image/captcha.
img = driver.find_element_by_xpath(".//*[@id='trRandom3']/td[2]/img")
src = img.get_attribute('src')
urllib.request.urlretrieve(src, "captcha.jpeg")

【问题讨论】:

  • 图像的 src 不一定(也可能不是)磁盘上的文件,但可能是动态生成的图像。每次请求端点时,都会创建一个新图像,并将 CAPTCHA 的“答案”存储在您的会话中。

标签: python selenium


【解决方案1】:

因为图像的src 的链接在您打开该链接后会给您一个随机的验证码图像!

除了从图片的src 下载文件外,您还可以截屏以在浏览器中获取该文件。不过需要下载Pillow(pip install Pillow),按照this answer中提到的方式使用:

from PIL import Image
from selenium import webdriver

def get_captcha(driver, element, path):
    # now that we have the preliminary stuff out of the way time to get that image :D
    location = element.location
    size = element.size
    # saves screenshot of entire page
    driver.save_screenshot(path)

    # uses PIL library to open image in memory
    image = Image.open(path)

    left = location['x']
    top = location['y'] + 140
    right = location['x'] + size['width']
    bottom = location['y'] + size['height'] + 140

    image = image.crop((left, top, right, bottom))  # defines crop points
    image.save(path, 'jpeg')  # saves new cropped image


driver = webdriver.Firefox()
driver.get("http://sistemas.cvm.gov.br/?fundosreg")

# change frame
driver.switch_to.frame("Main")

# download image/captcha
img = driver.find_element_by_xpath(".//*[@id='trRandom3']/td[2]/img")
get_captcha(driver, img, "captcha.jpeg")



driver = webdriver.Firefox()
driver.get("http://sistemas.cvm.gov.br/?fundosreg")

# change frame
driver.switch_to.frame("Main")

# download image/captcha
img = driver.find_element_by_xpath(".//*[@id='trRandom3']/td[2]/img")
get_captcha(driver, img, "captcha.jpeg")

(请注意,我已经稍微更改了代码,以便它适用于您的情况。)

【讨论】:

    【解决方案2】:

    您可以使用一段 Javascript 获取验证码的渲染图像。它比截取和裁剪屏幕截图更快:

    import base64
    from selenium import webdriver
    
    driver = webdriver.Firefox()
    driver.set_script_timeout(10)
    
    driver.get("http://sistemas.cvm.gov.br/?fundosreg")
    
    driver.switch_to.frame("Main")
    
    # find the captcha element
    ele_captcha = driver.find_element_by_xpath("//img[contains(./@src, 'RandomTxt.aspx')]")
    
    # get the captcha as a base64 string
    img_captcha_base64 = driver.execute_async_script("""
        var ele = arguments[0], callback = arguments[1];
        ele.addEventListener('load', function fn(){
          ele.removeEventListener('load', fn, false);
          var cnv = document.createElement('canvas');
          cnv.width = this.width; cnv.height = this.height;
          cnv.getContext('2d').drawImage(this, 0, 0);
          callback(cnv.toDataURL('image/jpeg').substring(22));
        }, false);
        ele.dispatchEvent(new Event('load'));
        """, ele_captcha)
    
    # save the captcha to a file
    with open(r"captcha.jpg", 'wb') as f:
        f.write(base64.b64decode(img_captcha_base64))
    

    【讨论】:

    • 此代码下载新图像,因此验证码不同。
    【解决方案3】:

    如果您已经加载了图像,而不是 execute_async_script,请使用

    import base64
    img_base64 = browser.execute_script("""
        var ele = arguments[0];
        var cnv = document.createElement('canvas');
        cnv.width = ele.width; cnv.height = ele.height;
        cnv.getContext('2d').drawImage(ele, 0, 0);
        return cnv.toDataURL('image/jpeg').substring(22);    
        """, browser.find_element_by_xpath("//your_xpath"))
    with open(r"image.jpg", 'wb') as f:
        f.write(base64.b64decode(img_base64))
    

    【讨论】:

    • 干净的答案,无需安装和导入重量级库。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-08-11
    • 2013-10-24
    • 1970-01-01
    • 2019-10-01
    • 2019-04-25
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多