简介:这份文档面向需要处理卫片图斑及大量地块出图任务的GIS从业者与ArcGIS初学者,聚焦按图斑批量生成JPG/PNG图片的自动化方案,帮助摆脱逐一手动出图的低效流程。内容围绕ArcGIS数据驱动页面与arcpy脚本展开,涵盖图层与名称字段设置、排序和显示范围、比例尺与布局动态文本,以及遍历页面导出图片、结果目录检查等环节,并给出可直接套用的Python示例与参数调整思路。包内为1个doc文档,压缩包约29KB,体积轻便,适合作为操作备忘或项目参考。已有8322人学习,说明其在批量出图场景中具有一定实用参考价值。读者可据此理解卫片图斑批量出图的核心流程,掌握动态信息展示与脚本导出方法,并迁移到类似地块调查、巡查举证等制图任务中。
1. 卫片图斑批量出图:明明只有三个图斑,却只出了两张
某开发者接了个活,一个卫片图斑层里躺着 1、2、3 三个图斑,要求每个图斑出一张 JPG,图名跟着图斑编号走。他翻出一段 ArcGIS 按图斑批量出图的脚本,跑完打开输出目录,只有两张图,第三张怎么都不出现;换到另一台机器上,脚本第一行就直接报语法错误。这两件事都不是代码写错了,而是卡在版本和前置配置上:ArcGIS 9 里根本没有 Data Driven Pages(数据驱动页面),而 10.x 自带的是 Python 2.7,跟现在随手搜到的 Python 3 写法对不上。这套环境在卫片核查、图斑台账、按村出图这类内业活里太常见了,装不对的后果也很直接——跑一半停、图名乱码、最后一张永远缺。下面这套流程是按 ArcGIS Desktop 10.2 起的版本走的,新手照着做能跑通,老手可以只看版本取舍和排错部分。
2. 环境准备:ArcGIS Desktop 10.2 自带的 Python 2.7 才是执行环境
动手装之前先把三件事定死:桌面版装哪个大版本、脚本用哪个 Python 解释器跑、编辑器用什么。这三件事只要错一件,后面配置数据驱动页面配得再漂亮,脚本也跑不起来。
2.1 三个版本变量:桌面版、Python、arcpy
很多人以为“装个 ArcGIS 就行”,实际上决定批量出图能不能成的是三个互相绑定的东西。第一个是桌面版大版本,Data Driven Pages 从 10.0 开始才有,所以 9.x 直接排除,10.2 及以上都可以,10.2 胜在稳定、单位里存量机器多、网上能查到的 arcpy.mapping 写法基本都对得上。第二个是 Python 解释器,10.x 安装时会把 Python 2.7 一起装进去,位置一般在C:\Python27\ArcGIS10.2\,这个解释器是独立的,和你系统里另外装的 Python 3 完全没关系。第三个是 arcpy 模块,它只存在于 ArcGIS 自带的那套 Python 里,你用系统的 Python 3 去import arcpy,一定报 ModuleNotFoundError。
提示:判断“我该用哪套写法”,看模块名就够了。
arcpy.mapping属于 Desktop 10.x,arcpy.mp属于 ArcGIS Pro。两者函数名相似但参数不同,复制粘贴时最容易在这里翻车。
下面这张对照表是我自己贴在便签上的,装环境前扫一眼能省不少时间:
| 对照项 | ArcGIS Desktop 10.2 ~ 10.8 | ArcGIS Pro |
|---|---|---|
| 分页出图机制 | Data Driven Pages | Map Series(地图系列) |
| 脚本解释器 | Python 2.7(随 Desktop 安装) | Python 3(随 Pro 安装) |
| 模块入口 | arcpy.mapping | arcpy.mp |
| 读取文档 | arcpy.mapping.MapDocument | arcpy.mp.ArcGISProject |
| 导出函数 | ExportToJPEG/ExportToPNG | exportToJPEG(布局对象方法) |
| print 写法 | print mapName或print(mapName) | 必须print(mapName) |
在命令行里验证解释器对不对,不需要打开 ArcMap,一条命令就够:
"C:\Python27\ArcGIS10.2\python.exe" -c "import arcpy; print(arcpy.GetInstallInfo()['Version'])"这段命令的意思是用 ArcGIS 自带解释器执行一段内联代码,导入 arcpy 后打印安装信息里的版本号。能打出版本号说明 arcpy 可用,路径写对;如果提示No module named arcpy,说明你调用的是别的 Python,回去检查路径里ArcGIS10.2这一段是不是写成了ArcGIS10.8或者干脆指向了C:\Python39。这一步别偷懒,后面所有报错里最难查的就是解释器错配。
2.2 ArcGIS Desktop 的安装顺序与授权配置
安装本身不难,坑在于顺序和路径。常见做法是:先确认机器上没有残留的其他版本 Desktop(有就先卸干净,不要两个大版本并存),然后装授权管理组件,再装 Desktop 主体。如果你的授权是浮动式的,先装 License Manager 并在里面完成授权文件配置,再装桌面端;如果是单机版,桌面端装完打开 ArcGIS Administrator,选单机版并完成授权,别一装完就去开 ArcMap,授权没落地会反复弹窗。
安装路径我一般坚持两条:全英文、无空格。D:\ArcGIS\Desktop10.2这种最好,别塞进D:\软件\地理信息 系统\下面。原因不在于 ArcGIS 本身装不上,而在于后面写的 mxd 路径、脚本路径、输出路径一旦含中文或空格,Python 2.7 在拼接字符串时很容易出编码问题,导出函数又不给你明确报错,只会一声不响地少出图。
装完先做三件事再谈脚本:打开 ArcMap 能正常启动、新建一个空白地图能保存成 mxd、工具箱能打开。这三步过了,说明桌面端和 Python 组件都齐了。至于 Python 组件是否真的注册好,可以用 2.1 里那条命令再验一次,两条路都通才算环境干净。
注意:安装过程中把所有 GIS 相关进程关掉,包括后台的地图服务、其他版本的 ArcCatalog。装到一半被占用导致组件注册失败,事后表现是“ArcMap 能开但 arcpy 导入报错”,这种半坏状态最难修,重装比排查快。
2.3 Notepad++ 装好之后,把 .py 的执行按钮配出来
脚本不一定非要用 Notepad++ 写,但用它的好处是改一行、按一下就能跑,不用来回切命令行。装最新版即可,安装时勾选“添加到右键菜单”会方便些。装完第一件事是设语言:菜单里找到语言选项,选 Python,这样缩进、关键字、注释颜色才正常——Python 靠缩进定逻辑,用纯文本编辑器写,一个 Tab 和空格的混用就够你查半小时。
第二件事是把运行命令绑上去。打开“运行”菜单的运行对话框,填入下面这行:
"C:\Python27\ArcGIS10.2\python.exe" "$(FULL_CURRENT_PATH)"这行的含义是:用 ArcGIS 自带解释器执行当前正在编辑的文件,$(FULL_CURRENT_PATH)是编辑器自带的变量,会被替换成当前文件的完整路径。填完点保存,给它一个快捷键,比如 Ctrl+F5。以后改完脚本直接按快捷键,输出窗口就在编辑器下方,报错信息第一行通常在最后几行里,往上翻能看到具体行号。
第三件事是编码。脚本开头那行# coding:utf-8只是声明,文件本身必须真的存成 UTF-8。Notepad++ 的编码菜单里选“UTF-8”(不带 BOM),别选“ANSI”,也别选带 BOM 的那个。带 BOM 时 Python 2.7 有时会在第一行报莫名其妙的语法错误,而不带 BOM 的 UTF-8 才能让中文图斑名正常参与字符串拼接。
3. 配置数据驱动页面:图层、名称字段、排序字段、显示范围和比例尺
数据驱动页面是整套方案的底座。它的作用是把索引图层里的每一条记录,映射成地图布局里的“一页”。你后面脚本做的事情,本质上就是遍历这些页、逐页导出。所以这一章配错,脚本写得再对也是错的结果。
3.1 启用数据驱动页面与索引图层的选取
在 ArcMap 里从自定义菜单找到工具栏,把数据驱动页面工具条调出来,点开设置。第一个要填的是图层,这里必须选那个卫片图斑层,而且它得是内容列表里的要素图层,不能是栅格、不能是注记图层、不能是图层组。有些人把图斑层放进了图层组里统一管理,直接选组是选不中的,得展开组选到具体的要素层。
选完图层后,页面会自动按要素数量生成。此时布局里会出现页面指示,左侧工具条上能翻页。如果翻页后地图范围没跟着动,八成是显示范围设置成了固定范围,回到设置里改成按要素范围自适应即可。
这里有个容易被忽略的前提:索引图层必须有明确的、唯一的标识字段。图斑层里如果只有系统自动生成的 ObjectID,也能用,但导出来的文件名就是一串流水号,后期人工核对时基本没意义。所以正式跑之前,先确认属性表里有一列能当图斑编号用的字段,哪怕是手工补的一列“图斑号”。
3.2 名称字段与排序字段:输出文件名到底从哪来
名称字段决定了每页的“页名”,而脚本里取的正是这个页名来做输出文件名。所以这一步实际上是在决定你最终拿到的一批 JPG 叫什么。我的做法是选图斑编号字段,形如 1、2、3 这种短编号,或者带前缀的编号。不建议直接选面积、类型这类可能重复或带小数点的字段,重复会导致文件互相覆盖,小数点在某些环境下会被当成路径分隔符处理。
排序字段是可选项,但建议填。按编号排序后,输出顺序稳定,出问题时你能快速判断是“第几张开始错”,而不是面对一堆乱序文件干瞪眼。按面积从大到小排序也常见,方便优先检查大图斑。
字段值还有两个硬性要求:不能为空,不能含 Windows 文件名非法字符。反斜杠、正斜杠、冒号、星号、问号、双引号、尖括号、竖线这九个字符只要出现一个,导出就会失败,而且报错位置往往指向导出函数那一行,很容易误判成 arcpy 的问题。我一般会在脚本里加一层清洗(第 4 章会给具体写法),而不是指望数据本身干净。
3.3 显示范围、比例尺与布局里的动态文本
显示范围这一项,决定每个图斑在图上占多大。选按要素自适应最省事,图斑大小不一也能各自填满布局;如果业务要求所有图统一比例尺(比如统一 1:10000 便于目视比对),就在比例尺框里写死数值,这时范围要选保持比例尺那一档,否则会出现图斑被裁切的情况。
比例尺的取舍需要说明:统一比例尺的好处是图与图之间可比,坏处是极大和极小的图斑会分别表现为“撑爆”和“一个点”。卫片核查类业务通常要求统一比例尺,那就接受小图斑看不清的事实,必要时在布局里额外插一个小比例尺的定位图。按要素自适应的好处是每张图都好看,坏处是不能横向比对,看你怎么选。
布局视图里还可以插入动态文本,这是让每张图自带信息的关键。插入菜单里的动态文本,能找到页名、页码,以及数据驱动页面属性里的字段,把村名、图斑面积、图斑类型这些字段插进去,每翻一页文本就自动跟着变。这一步做完,导出的 JPG 不只是地图截图,而是一张带属性信息的成果图。
配置完记得保存 mxd,保存路径同样遵守全英文无空格的原则。保存后建议先在 ArcMap 里手动翻几页,确认识别到的页名、比例尺、动态文本都对,再去写脚本。
4. 批量出图脚本:从 ExportToPNG 到 ExportToJPEG 的参数取舍
脚本本身不长,二十来行,但每一行都对应一个具体决定:文档怎么读、页怎么翻、名字怎么取、图怎么导。下面这版是在原始写法基础上补了目录创建、文件名清洗和异常提示的版本,能直接跑。
4.1 脚本骨架:MapDocument、currentPageID 与 pageRow
# coding:utf-8 import arcpy import os import re MXD_PATH = r"F:\GeoData\ProjectA\WeiPian.mxd" OUT_DIR = r"F:\GeoData\ProjectA\OutJPG" mxd = arcpy.mapping.MapDocument(MXD_PATH) ddp = mxd.dataDrivenPages if not os.path.isdir(OUT_DIR): os.makedirs(OUT_DIR) # 页码从 1 开始,到 pageCount 结束,必须 +1 for pageNum in range(1, ddp.pageCount + 1): ddp.currentPageID = pageNum mapName = ddp.pageRow.getValue(ddp.pageNameField.name) print(mapName)MapDocument负责把磁盘上的 mxd 读进内存,注意这里读的是文件而不是 ArcMap 里打开的那个窗口。dataDrivenPages拿到分页对象,前提是这个 mxd 已经按第 3 章配好了数据驱动页面,没配过的话这行会直接抛属性错误。currentPageID是当前页号,赋值即切换,取值范围 1 到pageCount,赋 0 会报错,这也是很多人踩的坑。pageRow返回当前页对应的那条记录,再用pageNameField.name拿到名称字段的字段名,getValue取出值,这个值就是页名,也就是后面要做文件名的东西。
中间那句print(mapName)建议保留。它不是给你看的,是给“跑到哪一张”留个痕迹:脚本中途崩了,输出窗口最后一行打印的图斑号就是崩的那张。
4.2 导出函数:PNG 换 JPEG 时要改哪几个参数
原始写法用的是ExportToPNG,业务要 JPG 就换成ExportToJPEG,参数名并不完全一样。我用关键字参数写,可读性好一些:
safe = re.sub(r'[\\/:*?"<>|]', '_', unicode(mapName).strip()) out_file = os.path.join(OUT_DIR, safe + ".jpg") arcpy.mapping.ExportToJPEG( mxd, out_file, resolution=200, # 输出 DPI jpeg_quality=90 # 1-100,越大越清晰、体积越大 ) print("done")第一个参数是文档对象,传mxd而不是路径,导出时它会按照当前页号的状态渲染。第二个参数是完整输出路径,必须是绝对路径,且目录要事先存在,否则报 IOError。resolution控制 DPI,200 适合屏幕查看和打印小样,要印刷级就到 300,代价是文件体积和耗时成倍增长。jpeg_quality只在 JPEG 导出里有,80 到 95 是常用区间,低于 70 图斑边界会发虚,高于 95 体积涨得快但肉眼几乎看不出差别。
如果业务还要求带坐标信息,ExportToJPEG有个world_file参数,置 True 会在同目录多生成一个坐标辅助文件。多数核查场景不需要,开了反而让输出目录看着乱。至于宽高,df_export_width和df_export_height是像素尺寸,不填就按布局的页面尺寸和 DPI 自动算,一般不用动;只有需要固定出图像素尺寸的批量任务才指定。
提示:函数名从 PNG 换成 JPEG 之后,别只改函数名不改参数。PNG 有透明色和伽马参数,JPEG 没有;JPEG 有质量参数,PNG 没有。混着写的结果是执行时报“参数类型不匹配”,而报错信息不会告诉你具体是哪个参数。
4.3 输出路径、文件名清洗和一批出图的收尾
文件名清洗那行值得单独说。unicode(mapName).strip()先转成 Unicode 再去首尾空白,Python 2.7 下中文名必须这么处理,否则拼接路径时可能抛编码异常。re.sub把九个非法字符统一替换成下划线,比逐个replace干净。替换完如果变成空字符串(原值为空或全是非法字符),得给个兜底名,比如拼上页号,否则一堆空名文件会互相覆盖,最后你只得到一个文件。
输出目录建议按批次分开,比如按日期或按任务名建子目录,别所有批次都往同一个文件夹里倒。同一次任务重跑时,先清空目录再跑,不然上次的残留会混在结果里,核对文件数时永远对不上。
脚本跑完后print("done")是给自己一个明确结束信号。如果输出窗口里最后一行是某个图斑号而不是 done,说明是在那一张崩的,直接拿那个图斑号去属性表里查,八成是名称字段有非法字符或空值。
5. 避坑与排查:五个让批量出图中途停下的问题
这几条都是我在实际任务里撞过的,按“现象、原因、解决”记下来,下次遇到能直接对号入座。
5.1 输出比图斑少一张:循环少写了一页
现象是图层里有 3 个图斑,输出目录只有 2 张图,缺的永远是最后一个。原因是页码循环写成了range(1, pageCount),Python 的 range 不包含结束值,实际只跑到pageCount - 1。解决很简单,写成range(1, ddp.pageCount + 1)。这个坑的隐蔽之处在于,图斑多的时候只少一张,肉眼很难发现,等交付后被人指出来才回头查。
5.2 中文图斑名报编码错误或输出乱码文件名
现象是脚本跑到含中文的图斑号时抛 UnicodeEncodeError,或者文件生成了但名字是乱码。原因通常是脚本文件本身存成了 ANSI,而开头声明写的是 utf-8,声明和实际编码不一致。解决办法是用编辑器把文件另存为不带 BOM 的 UTF-8,同时在拼接路径前用unicode()转换字段值。如果输出目录里已经有一批乱码文件,直接删掉重跑,不要试图改名,改到最后往往对不上号。
5.3 报“对象没有 dataDrivenPages 属性”
现象是执行到取分页对象那一行直接报属性错误。原因有三种:mxd 根本没配数据驱动页面;配了但保存后又被改回去;或者脚本里 mxd 路径写错,指向了一个普通地图文档。解决方式是先在 ArcMap 里打开那个 mxd,把数据驱动页面工具条调出来看是否处于启用状态,确认后重新保存;再把脚本里的路径用原始字符串r"..."写,避免反斜杠被当转义符。
5.4 所有图导出来长得一模一样
现象是文件数量对,但每张图内容都是同一个图斑,或者都是空白。原因多半是显示范围被设成了固定范围,页号切换了但地图没跟着变;另一种可能是索引图层的要素范围异常,比如某个图斑的几何为空,导致布局定位失败。解决是先手动在 ArcMap 里翻几页,看范围是否跟着动;再检查索引图层属性表,把几何为空的记录挑出来排除掉。空白图还有个小概率原因:数据框被锁定,导出时没按当前页重绘,重启 ArcMap 后重跑通常能恢复正常。
5.5 用错解释器,第一行就语法错误
现象是脚本第一行print mapName报缺少括号之类的语法错误。原因是用了系统里的 Python 3 去执行 Python 2.7 的代码。解决办法是回到编辑器,把运行命令里的解释器路径换成 ArcGIS 自带那个,或者把代码改成print(mapName)这种两种版本都兼容的写法。判断当前用的是哪个解释器,在脚本开头加一行打印即可:
import sys print(sys.version)跑出来是 2.7.x 就对了,是 3.x 说明解释器选错。这条加上去之后别删,留着当自检。
6. 装完怎么验证:先拿三个图斑跑小样,再全量
批量出图最怕的不是跑不起来,是跑起来了结果不对却没人发现。我的固定做法是先小样后全量:把索引图层筛成三个图斑——一个普通大小的、一个特别小的、一个名称里带空格或括号的,用这份筛选后的图层跑一遍脚本,三个文件都对,再放全量。小样阶段盯三件事:文件数是否等于图斑数、每张图的动态文本是否跟着变、文件名是否与图斑编号完全一致。
文件名和图斑的对应关系,靠肉眼对不现实,用一段校验脚本扫一遍更可靠:
# coding:utf-8 import os OUT_DIR = r"F:\GeoData\ProjectA\OutJPG" files = [f for f in os.listdir(OUT_DIR) if f.lower().endswith(".jpg")] print("count:", len(files)) for f in files: size = os.path.getsize(os.path.join(OUT_DIR, f)) if size < 10240: # 小于 10KB 基本可判定为空白图 print("suspect:", f, size)这段脚本做两件事:统计输出目录里 jpg 的数量,和索引图层的记录数做个对比;逐个检查文件体积,把小于 10KB 的挑出来。空白图或者只导出了边框的图,体积通常就是几 KB,用这个阈值能快速筛出可疑项。阈值不是死的,图斑密集、底图复杂的区域正常图可能就二三十 KB,按自己那批数据调。
数量对、体积正常之后,还有一步不能省:随机打开三五张,看布局里的动态文本是不是当前图斑的信息。这一步专门抓“页名对但内容错”的情况,常见于动态文本绑错了字段,或者数据驱动页面的名称字段后来改过但地图没重新保存。三张里有一张对不上,就回到第 3 章重新核对字段绑定。
从那以后我每次接批量出图的活,都强制自己先跑三个图斑的小样,跑完再全量,不管这套脚本我已经用过多少回。批量任务出错的代价从来不在跑的那几分钟,而在交付之后被返回来重做。希望帮到你。
本文还有配套的精品资源,点击获取