热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python提取那些被“标记”照片的实例详解

这篇文章主要介绍了用python找出那些被“标记”的照片的相关资料,需要的朋友可以参考下
这篇文章主要介绍了用python找出那些被“标记”的照片的相关资料,需要的朋友可以参考下

源码传送门

环境准备

下面的两个第三方模块都可以直接通过pip快速安装,这里使用py36作为运行环境。

  • python3.6

  • requests

  • exifread

思路

  1. 遍历目录

  2. 拉取数据集合

  3. 遍历集合取得exif

  4. exif信息整理,并获取实体地址

  5. 拷贝文件到结果样本目录

  6. 生成json报告文件

基础知识

下面是现今相片中会存在与GPS相关的关键字,大牛亦可一比带过~ [参考]

{
 "GPSVersionID": "GPS版本",
 "GPSLatitudeRef": "南北纬",
 "GPSLatitude": "纬度",
 "GPSLongitudeRef": "东西经",
 "GPSLongitude": "经度",
 "GPSAltitudeRef": "海拔参照值",
 "GPSAltitude": "海拔",
 "GPSTimeStamp": "GPS时间戳",
 "GPSSatellites": "测量的卫星",
 "GPSStatus": "接收器状态",
 "GPSMeasureMode": "测量模式",
 "GPSDOP": "测量精度",
 "GPSSpeedRef": "速度单位",
 "GPSSpeed": "GPS接收器速度",
 "GPSTrackRef": "移动方位参照",
 "GPSTrack": "移动方位",
 "GPSImgDirectionRef": "图像方位参照",
 "GPSImgDirection": "图像方位",
 "GPSMapDatum": "地理测量资料",
 "GPSDestLatitudeRef": "目标纬度参照",
 "GPSDestLatitude": "目标纬度",
 "GPSDestLongitudeRef": "目标经度参照",
 "GPSDestLongitude": "目标经度",
 "GPSDestBearingRef": "目标方位参照",
 "GPSDestBearing": "目标方位",
 "GPSDestDistanceRef": "目标距离参照",
 "GPSDestDistance": "目标距离",
 "GPSProcessingMethod": "GPS处理方法名",
 "GPSAreaInformation": "GPS区功能变数名",
 "GPSDateStamp": "GPS日期",
 "GPSDifferential": "GPS修正"
}

初始化

考虑到exifread的模块中有大量的logging输出,这里将它的level级别调到最高。 然后下边的KEY是某站在高德地图API的时候遗留下来的 我也很尴尬。。就当福利了

import os
import time
import json
import random
import logging
import requests
import exifread
logging.basicConfig(level=logging.CRITICAL)
KEY = "169d2dd7829fe45690fabec812d05bc3"

主逻辑函数

def main():
 # 预设后缀列表
 types = ["bmp", "jpg", "tiff", "gif", "png"]
 #结果数据集合
 picex = []
 # 文件存储路径
 saves = "$" + input("| SavePath: ").strip()
 # 文件搜索路径 并遍历所有文件返回文件路径列表
 pools = jpgwalk(input("| FindPath: "), types)
 #存储目录
 savep = "%s/%s" % (os.getcwd().replace("\\", "/"), saves)
 if savep in pools:
 pools.remove(savep)
 # 遍历数据集并获取exif信息
 for path in pools:
 res = getEXIF(path)
 if res:
  picex.append(res)
 # 结果报告
 print("| Result %s" % len(picex))
 # 如果存在结果 保存结果到json并讲相关图片复制到该目录下
 if picex:
 #创建目录
 if not os.path.exists(saves):
  os.mkdir(saves)
 #生成一个4格缩进的json文件 
 with open("%s/%s.json" % (saves, saves), "wb") as f:
  f.write(json.dumps(picex, ensure_ascii=False, indent=4).encode("utf8"))
 #copy图像到该目录
 for item in picex:
  source_path = item["Filename"]
  with open("%s/%s" % (saves, source_path.split("/")[-1]), "wb") as f_in:
  with open(source_path, "rb") as f_out:
   f_in.write(f_out.read())

遍历方法

遍历指定及其所有下级目录,并返回全部的图片的路径集合,这里要注意的是每次扫描后的拷贝行为都会生成缓存,所以通过指定 $ 来避开。

# 获取指导目录全部的图片路径
def jpgwalk(path, types):
 _start = time.time()
 _pools = []
 # 遍历该目录 并判断files后缀 如符合规则则拼接路径
 for _root, _dirs, _files in os.walk(path):
 _pools.extend([_root.replace("\\", "/") + "/" +
   _item for _item in _files if _item.split(".")[-1].lower() in types and "$" not in _root])
 #报告消耗时间
 print("| Find %s \n| Time %.3fs" % (len(_pools), time.time() - _start))
 return _pools

经纬度格式化

度分秒转浮点,方便api调用查询,因为存在一些诡异的数据比如 1/0,所以默认返回0

def cg(i):
 try:
 _ii = [float(eval(x)) for x in i[1:][:-1].split(', ')]
 _res = _ii[0] + _ii[1] / 60 + _ii[2] / 3600
 return _res
 except ZeropisionError:
 return 0

EXIF信息整理

考虑到大部分的设备还未开始支持朝向、速度、测量依据等关键字,这里暂时只使用比较常见的,如有需要的朋友可以自行添加。毕竟得到的信息越多对社工有更大的帮助。

def getEXIF(filepath):
 #基础关键字
 _showlist = [
 'GPS GPSDOP',
 'GPS GPSMeasureMode',
 'GPS GPSAltitudeRef',
 'GPS GPSAltitude',
 'Image Software',
 'Image Model',
 'Image Make'
 ]
 #GPS关键字
 _XYlist = ["GPS GPSLatitude", "GPS GPSLongitude"]
 #时间关键字
 _TimeList = ["EXIF DateTimeOrigina", "Image DateTime", "GPS GPSDate"]
 #初始化结果字典
 _infos = {
 'Filename': filepath
 }
 with open(filepath, "rb") as _files:
 _tags = None
 # 尝试去的EXIF信息
 try:
  _tags = exifread.process_file(_files)
 except KeyError:
  return
 # 判断是否存在地理位置信息
 _tagkeys = _tags.keys()
 if _tags and len(set(_tagkeys) & set(_XYlist)) == 2 and cg(str(_tags["GPS GPSLongitude"])) != 0.0:
  for _item in sorted(_tagkeys):
  if _item in _showlist:
   _infos[_item.split()[-1]] = str(_tags[_item]).strip()
  # 经纬度取值
  _infos["GPS"] = (cg(str(_tags["GPS GPSLatitude"])) * float(1.0 if str(_tags.get("GPS GPSLatitudeRef", "N")) == "N" else -1.0),
    cg(str(_tags["GPS GPSLongitude"])) * float(1.0 if str(_tags.get("GPS GPSLongitudeRef", "E")) == "E" else -1.0))
  # 获取实体地址
  _infos["address"] = address(_infos["GPS"])
  # 获取照片海拔高度
  if "GPS GPSAltitudeRef" in _tagkeys:
  try:
   _infos["GPSAltitude"] = eval(_infos["GPSAltitude"])
  except ZeropisionError:
   _infos["GPSAltitude"] = 0
  _infos["GPSAltitude"] = "距%s%.2f米" % ("地面" if int(
   _infos["GPSAltitudeRef"]) == 1 else "海平面", _infos["GPSAltitude"])
  del _infos["GPSAltitudeRef"]
  # 获取可用时间
  _timeitem = list(set(_TimeList) & set(_tagkeys))
  if _timeitem:
  _infos["Dates"] = str(_tags[_timeitem[0]])
  return _infos

地址转换

一个简单的爬虫,调用高德地图api进行坐标转换,考虑到原本是跨域,这里添加基础的反防爬代码。这里有个小细节,海外的一律都取不到(包括台湾),可以通过更换googlemap的api来实现全球查询。

def address(gps):
 global KEY
 try:
 # 随机UA
 _ulist = [
  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
  "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0",
  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; 360SE)",
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
  "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
  "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)",
  "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)",
  "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Firefox/0.10",
  "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; ja) Presto/2.10.289 Version/12.00",
  "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36"
 ]
 # 伪造header
 _header = {
  "User-Agent": random.choice(_ulist),
  "Accept": "text/Javascript, application/Javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01",
  "Accept-Encoding": "gzip, deflate, sdch",
  "Accept-Language": "zh-CN,zh;q=0.8",
  "Referer": "http://www.gpsspg.com",
 }
 _res = requests.get(
  "http://restapi.amap.com/v3/geocode/regeo?key={2}&s=rsv3&location={1},{0}&platform=JS&logversion=2.0&sdkversion=1.3&appname=http%3A%2F%2Fwww.gpsspg.com%2Fiframe%2Fmaps%2Famap_161128.htm%3Fmapi%3D3&csid=945C5A2C-E67F-4362-B881-9608D9BC9913".format(gps[0], gps[1], KEY), headers=_header, timeout=(5, 5))
 _json = _res.json()
 # 判断是否取得数据
 if _json and _json["status"] == "1" and _json["info"] == "OK":
  # 返回对应地址
  return _json.get("regeocode").get("formatted_address")
 except Exception as e:
 pass

实例

运行该代码 然后输入保存文件夹名和扫描位置即可

python排序算法大全

以上就是python提取那些被“标记”照片的实例详解的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • python限制递归次数(python最大公约数递归)
    本文目录一览:1、python为什么要进行递归限制 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
author-avatar
法华大道暴力喵一只
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有