python解析Exif元数据

元数据

从文件中提取元数据。文件不是清晰可见 的对象,元数据可以存在于文档,电子表格,图像,音频和视频等文件类型中。 创作应用程序可能会存储一些细节如文件的作者,创建和修改时间,潜在的修订和注释。例如,拍照手机可以标记本地的GPS在照片中或者微软的 Word 应用程序可以存储文档的作者。检查每一个文件是个艰难的任务,我们可以使用Python自动处理。

使用PyPDF解析PDF元数据

PyPDF 是一个优秀的第三方管理 PDF 文件很实用的库,它提供了文档的信息提取,分割,合并,加密 和解密的能力。

为了提取元数据,我们使用函数 getDocumentInfo()。这个方法返回一个元组数组,每一个元组包含一个元数据元素和它的值。遍历这个数组并打印 PDF 文件的全部元数据。

# coding = utf-8
import pyPdf
from pyPdf import PdfFileReader
import optparse


def printMeta(fileName):
    pdfFile = PdfFileReader(file(fileName, 'rb'))
    docInfo = pdfFile.getDocumentInfo()
    print('[*]PDF MetaData FOr:' + str(fileName))
    for metaItem in docInfo:
        print('[+]' + metaItem + ':' + docInfo[metaItem])


def main():
    parser = optparse.OptionParser('usage %prog -F ')
    parser.add_option('-F', dest='fileName', type='string', help='specify PDF file name')
    (options, args) = parser.parse_args()
    fileName = options.fileName
    if fileName == None:
        print(parser.usage)
        exit(0)
    else:
        printMeta(fileName)


if __name__ == '__main__':
    main()

理解Exif元数据

Exif 是一种图象文件格式,它的数据存储与 JPEG 格式是完全相同的。实际上 Exif 格式就是在 JPEG 格式头部插入了数码照片的信息,包括拍摄时的光圈、快 门、白平衡、ISO、焦距、日期时间等各种和拍摄条件以及相机品牌、型号、 色彩编码、拍摄时录制的声音以及全球定位系统(GPS)、缩略图等。简单地Exif=JPEG+拍摄参数。

Phil Harvey 编写了一个实用的工具名 叫 exiftool(从 http://www.sno.phy.queensu.ca/~phil/exiftool/可获得)能解析这 些参数。

investigator$ exiftool photo.JPG
ExifTool Version Number : 8.76
File Name : photo.JPG
Directory : /home/investigator/photo.JPG
File Size : 1626 kB
File Modification Date/Time : 2012:02:01 08:25:37-07:00
File Permissions : rw-r--r--
File Type : JPEG
MIME Type : image/jpeg
Exif Byte Order : Big-endian (Motorola, MM)
Make
: Apple
Camera Model Name : iPhone 4S
Orientation : Rotate 90 CW
<..SNIPPED..>
GPS Altitude : 10 m Above Sea Level
GPS Latitude : 89 deg 59' 59.97" N
GPS Longitude : 36 deg 26' 58.57" W
<..SNIPPED..>

建立一个脚本来连接web网站,下载图像,并检测他们的Exif元数据。

使用BeautifulSoup下载图像

BeautifulSoup允许我们快速的解析HTML和 XML文档,使用BeautifulSoup来抓取HTML文档的内容来获取文档中所有的图像。使用urllib2打开文档来读取它,可以创造Beautiful对象或者包含一个不同HTML文档对象的解析树。用这样的对象, 我么可以提取所有的图像标签,通过使用 findall(‘img’)函数,这个函数返回一 个包含所有图像标签的数组。

import urllib2
from bs4 import BeautifulSoup


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

从网站中下载每一个图像,然后在单独的函数中进行检查。 为了下载图像,我们将用到 urllib2,urlparse 和 os 模块。首先,我们从图像标 签中提取源地址,接着我们读取图像的二进制内容到一个变量,最后我们以写- 二进制模式打开文件将图像内容写入文件。

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

使用python的图像库从图像阅读Exif元数据

为了测试图像的内容特到 Exif 元数据,我们将使用 Python 图像库 PIL 来处理文 件,可以从 http://www.pythonware.com/products/pil/获得,以增加 Python 的 图像处理能力,并允许我们快速的提取与地理位置相关的元数据信息。为了测 试文件元数据,我们将打开的对象作为 PIL 图像对象并使用函数 getexif()。接 下来我们解析 Exif 数据到一个数组,通过元数据类型索引。数组完成后,我们 可以搜索数组看看它是否包含有 GPSInfo 的 Exif 参数。如果它包含 GPSInfo 参 数,我们就知道对象包含 GPS 元数据并打印信息到屏幕上。

from PIL import Image
from PIL.ExifTags import TAGS

def testForExif(imgFileName):
    try:
        exifData = {}
        imgFile = Image.open(imgFileName)
        info = imgFile._getexif()
        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')
    except:
        pass

整合

将所有的包装在一起,可以连接到一个URL地址,解析并下载所有的图像文件,然后测试每个文件的Exif元数据。

main()函数中,首先获得站点上的所有图像的列表,然后对数据中的每一个图像,我们将下载并测试它的GPS元数据

# coding =UTF-8
import urllib2
import optparse
from bs4 import BeautifulSoup
from urlparse import urlsplit
from os.path import basename
from PIL import Image
from PIL.ExifTags import TAGS


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])
        imgFle = open(imgFileName, 'wb')
        imgFle.write(imgContent)
        imgFle.close()
        return imgFileName
    except:
        return ''


def testForExif(imgFileName):
    try:
        exifData = {}
        imgFile = Image.open(imgFileName)
        info = imgFile._getexif()
        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')
    except:
        pass


def main():
    parser = optparse.OptionParser('usage%prog -u ')
    parser.add_option('-u', dest='url', type='string', help='specify url address')
    (options, args) = parser.parse_args()
    url = options.url
    if url == None:
        print(parser.usage)
        exit(0)
    else:
        imgTags = findImages(url)
        for imgTag in imgTags:
            imgFileName = downloadImage(imgTag)
            testForExif(imgFileName)

if __name__ == '__main__':
    main()
forensics: # python exifFetch.py -u
http://www.flickr.com/photos/dvids/4999001925/sizes/o
[+] Finding images on
http://www.flickr.com/photos/dvids/4999001925/sizes/o
[+] Dowloading image...
[+] Dowloading image...
[+] Dowloading image...
[*] 4999001925_ab6da92710_o.jpg contains GPS MetaData
[+] Dowloading image...
[+] Dowloading image...
[+] Dowloading image...

你可能感兴趣的:(web)