如何使用Python PIL下载图像并提取Exif数据?

2 投票
2 回答
2736 浏览
提问于 2025-04-18 10:47

我正在尝试从下载的图片中读取Exif数据。我在一个函数中把图片保存到我的电脑,然后在另一个函数中尝试读取这些数据,但我总是遇到“坏模式”的错误。我能从一个预先保存的图片中读取数据,只需使用 ._getexif() 方法,但当我尝试对下载的图片做同样的事情时,它就不工作了。我到底哪里出错了呢?

这是调用这两个函数的循环。

else:
    imgTags = findImages(url)
    for imgTag in imgTags:
        imgFileName = downloadImage(imgTag)
        testForExif(imgFileName)

从页面上找到并下载图片

def findImages(url):
    print '[*] Finding images on ' + url
    urlContent = urllib2.urlopen(url).read()
    soup = BeautifulSoup(urlContent)
    imgTags = soup.findAll('img')
    return imgTags

def downloadImage(imgTag):
    try:
        print '[+] Downloading image...'
        imgSrc = imgTag['src']
        imgContent = urllib2.urlopen(imgSrc).read()
        imgFileName = basename(urlsplit(imgSrc)[2])
        imgFile = open(imgFileName, 'wb')
        imgFile.write(imgContent)
        imgFile.close()
        return imgFileName
    except:
        return ''

读取Exif数据

def testForExif(imgFileName):
    exifData = {}
    imgFile = Image.open(imgFileName, 'rb')
    info = imgFile._getexif()
    print '\n\n' + str(info) + '\n\n'
    if info:
        for (tag, value) in info.items():
            decoded = TAGS.get(tag, tag)
            exifData[decoded] = value
        exifGPS = exifData['GPSInfo']
        if exifGPS:
            print '[+] ' + imgFileName + ' contains GPS MetaData'

我认为“坏模式”错误是在 testsForExif 函数中触发的,可能是在前几行代码里。它从来没有执行到第一个打印语句。

我遇到的具体错误是:

ValueError: Bad Mode

追踪信息(最近的调用在前): 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 59 行, 在 main() 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 56 行, 在 main testForExif(imgFileName) 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 31 行, 在 testForExif imgFile = Image.open(imgFileName, 'rb') 文件 "C:\Python27\lib\site-packages\PIL\Image.py",第 1947 行, 在 open raise ValueError("bad mode") ValueError: bad mode

通过尝试,我还得到了一个:

Bad Mode 'rb', filename;

的错误。

我感到很困惑。

编辑:如果我把:

imgFile = Image.open(imgFileName, 'rb')

改成

imgFile = Image.open(imgFileName)

我就会得到 AttributeError: _getexif() 的错误,追踪信息:

追踪信息(最近的调用在前): 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 59 行, 在 main() 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 56 行, 在 main testForExif(imgFileName) 文件 "C:\Users\HeyNow\Downloads\Python\Cookbook\Forensics\metaurl.py",第 32 行, 在 testForExif info = imgFile._getexif() 文件 "C:\Python27\lib\site-packages\PIL\Image.py",第 512 行, 在 getattr raise AttributeError(name) AttributeError: _getexif

2 个回答

-1

你不需要特别定义 rb 模式,只需简单使用:

Image.open(imgFileName)

其实 Image.open() 只接受 r 模式(这是默认的模式)。你可以在 这里 查看相关信息。

1

我觉得你遇到错误是因为“downloadImages”这个功能的工作方式。你在出现错误的时候只是返回了一个空字符串。但是,在你的testforexif里,你没有检查文件名是否为空字符串就直接尝试打开它。

Image.open('') 

这样会导致imgfile变成None。这样一来,它就没有任何属性了,所以你会遇到属性错误。

可能在你解析网页或者处理文件名的过程中出现了一些错误,这些错误导致了程序出问题。处理错误不当是很糟糕的做法,而在这个情况下,它让你的程序完全无法运行。你虽然有try/except语句,但即使出现错误你还是继续执行。你需要做的是修改except部分,让它在出现错误(或者文件名为空)时跳过那个文件名。希望这能帮到你。

编辑:

建议你在执行过程中打印出一些变量(比如文件名),以确保它们是正确的,并且图片确实存在。也可能是文件类型的问题。例如,也许你的脚本找到了某些不是jpg格式的图片文件,然后试图打开bmp格式的exif数据等等。

撰写回答