
“苹果自动化脚本怎么选路线”这个问题我在不同的群里已经回答过很多次。每一次都有人直接问用快捷指令还是 Python有没有现成的自动化脚本推荐我的回答基本都先反问一句你每天在设备上重复做的事情到底是哪几件如果答不上来那工具推荐再多也是白搭。以前我刚换到 Mac 上的时候也恨不得把所有自动化工具都装一遍结果一个月后大部分都在吃灰。真正留下来天天用的反而是根据真实重复动作挑出来的那几套。这篇文章我就按这个思路讲先把重复动作分好类再对照着选路线、写脚本、避坑最后给你可以直接抄的落地例子。1. 把“重复动作”拆成可自动化的三类活先说结论绝大多数可以写脚本的重复动作都能归进三类——数据搬运、批量加工、状态触发。分类的意义不只是方便描述而是每一类对应的技术路线和工具层级完全不同。数据搬运类偏轻快捷指令能搞定批量加工类偏重Python 是主力状态触发类讲究“时机”系统自带的自动化和定时器更擅长。先把每天的动作归堆后面选路线的争议就少了大半。1.1 数据搬运类数据搬运类说白了就是信息从 A 挪到 B中间不加工或者只做很轻的加工。举个例子每天从网页上复制一段文字粘到表格里某个单元格把邮件附件下载下来移到指定文件夹把 APP 里的报价数字抄进记账软件。这类动作的共同特征是步骤固定数量不大不需要复杂的条件判断但它特别消耗耐心。它的自动化价值在于省掉“反复切窗口”的手工动作。我见过不少同事天天手动把多个来源的清单内容一个字一个字敲进表格其实这种活儿用快捷指令做一次把“获取剪贴板—替换文本—写入备忘录/表格”串起来就行。判断一个动作是不是数据搬运类你就问自己如果让我把同样的内容再复制一遍我能不能闭着眼完成能就是搬运优先考虑最轻的工具。1.2 批量加工类批量加工类和搬运的区别在于加工的对象是一批而且每个对象都要执行同一条处理链。比如把一个月拍摄的几百张照片统一压缩到适合发送的尺寸把下载目录里几十个文件按项目规则重命名把导出的日志里的空值和重复记录清掉。这类任务单看每个步骤不难但“一批”这个规模决定了靠手点会崩溃靠快捷指令也会很痛苦——快捷指令处理单条文本很快让它循环处理几百个文件时既慢又不好定位错误。这种时候 Python 几乎是唯一舒服的选项。我实际做过的一个最满意的小脚本就是把一年散落在各处的账单 CSV 合并成一张汇总表运行一次不到一秒换手动操作至少要一个下午。批量加工类的关键词是“循环”只要你的重复动作里藏着循环优先考虑 Python 或者至少是能跑循环的脚本环境。1.3 状态触发类第三类状态触发类重点是“在什么条件下自动发生”而不是动作本身。比如每天上午 9 点半自动抓取某个公开页面并保存快照连接上公司 Wi-Fi 自动把勿扰模式打开电池低于 30% 弹提醒或者某个文件夹有新文件进来就自动触发备份。这类任务的核心矛盾是触发源的多样性时间触发用系统计划任务最稳位置触发用快捷指令的自动化最方便文件夹变动触发则更适合 macOS 的文件夹操作或者脚本监听。很多人一开始把这类任务硬写成死循环脚本挂在后台一直跑这在个人电脑上既耗电又容易误事。更合适的做法是让操作系统来“叫人”你只写被叫醒之后要做的事。状态触发类设计对了之后几乎是无感的它不像前两类需要你主动调用而是自己在后台守着。2. 苹果生态里的三条自动化路线各管一段讲完需求分类再来看工具。苹果生态里真正能撑起日常自动化的我总结下来就三条路线快捷指令、Python 脚本、UI 级模拟。它们不是竞争关系而是分工关系。我见过太多人只盯着一个工具使劲最后把一个简单任务搞得非常复杂。下面把每一条路线的能力边界讲清楚方便你对照着选。2.1 快捷指令轻量动作编排人人可上手的入门线快捷指令是苹果系统自带的图形化自动化工具iPhone、iPad、Mac 上都有而且可以在设备之间同步。它最擅长的是处理“系统已经开放接口”的那类轻任务剪贴板、照片、文件、日历、提醒事项、URL 请求、基础文本替换等等。我对它的定位是“动作编排的胶水层”——很多繁琐的跨应用操作本质上就是几个系统动作首尾相接快捷指令几分钟就能拼出来。举个例子我每天要从网页复制文章粘贴到编辑器里复制下来的内容总带着一堆格式和链接尾巴。我就建了一条快捷指令获取剪贴板做几轮正则替换清掉空行和追踪链接再放回剪贴板绑定一个全局快捷键全程不到一秒。这类任务如果写 Python 反而麻烦因为要处理剪贴板权限、图形界面跳转那些事。另外快捷指令不需要频繁处理权限弹窗绝大多数系统能力它都能直接调对新手非常友好。它的短板也很明显不适合大批量处理不适合复杂循环和分支。几百条数据跑起来速度感人出错时又很难定位到底是哪一步出了问题。所以遇到“一条一条处理”的任务先想快捷指令遇到“一百条一百条处理”的任务就别为难它了。2.2 Python 脚本批量处理和数据分析的真正主力如果你每天重复做的事情里出现了“文件目录”“批量重命名”“Excel/CSV”“网页数据”“正则表达式”这些词Python 就是主力路线。macOS 自带 Python3再装一个 VS Code 或者直接写 .py 文件用终端跑依赖用 pip 管理这套组合在个人自动化领域非常成熟。Python 的优势不在于用起来多简单而在于它有完整生态pathlib 管文件、openpyxl/pandas 管表格、requests 管网络、BeautifulSoup 管网页解析、Pillow 管图片处理。我写过批量压缩图片的脚本把一整个文件夹的照片遍历一遍超过尺寸就压缩输出到新目录全程几秒钟代码二十行不到。这类活你用任何点击模拟工具去做都是灾难——每个文件点一次几百个文件点几百次中间只要弹出一个对话框整个流程就断了。不过 macOS 上的 Python 有几个坑值得提前知道。一是系统自带的 python3 和你后来装的库可能不在同一个环境里终端里装好的包换个方式调用就找不到。二是 launchd 定时任务跑脚本时 PATH 会被清空第三方库 import 直接失败。后面定时抓取那节我会专门演示怎么绕开这个坑。2.3 UI 级模拟兜底方案尽量不要一上来就选它UI 级模拟也就是通过脚本模拟鼠标点击、键盘输入、菜单选择去操作系统界面上的动作。它是三条路线里最容易被新手盯上的一条因为看起来“什么都能点”。但实际玩过的人都知道它有多脆页面改版就失效按钮位置一变脚本就白写而且需要辅助功能权限跑起来还会挡住鼠标光标期间没法做别的事。我自己的使用原则是只有当目标应用既没有提供导出功能、也没有命令行接口、也没有 AppleScript 支持时才会考虑用 UI 模拟。比如某个老软件只能通过菜单导入数据那就只能靠 System Events 模拟按键。但前提是任务确实非做不可而且你能接受脚本三天两头维护。另外提醒一句iOS 端你几乎找不到“可信任的通用点击模拟工具”系统限制很严所有宣称能自动点击的类工具都存在不小的隐私和审核风险。如果手机上的重复动作比较多优先走快捷指令的自动化事件不要折腾点击模拟。3. 需求到路线的匹配方法一张判断表和三个判断问题分类清楚了路线也清楚了接下来就解决“选”的问题。我给自己的选型流程很简单先回答三个问题再看判断表不再纠结。3.1 三个判断问题第一个问题这个动作发生在哪个平台上iPhone 上锁屏状态下的轻交互走快捷指令明显更顺Mac 上前台大量导入导出数据Python 更稳。不过很多任务是跨设备的比如手机上先产生内容最后要落到 Mac 上这种可以把快捷指令作为入口再通过共享菜单或“存储到 Mac 文件夹”转给后续脚本。第二个问题要处理的数据是“一条”还是“一堆”一条数据比如一段文字、一张截图、一个提醒快捷指令足够。一堆数据比如几百行表格、几百张图片、几个 GB 的文件直接上 Python。这个判断最直观也最不费脑。第三个问题如果脚本跑错了损失大不大纯读取类任务错了重跑一次就行风险低可以把自动化范围放得宽一点。如果是删除文件、发送消息这类不可逆操作尽量用脚本做“准备动作”最后一步保留人工确认。这三个问题分别回答的是平台、规模、容错率它们几乎决定了一切。3.2 路线选型判断表任务类型典型场景首选路线备选路线单条轻搬运复制文字、清洗剪贴板、快速记录快捷指令手工不推荐批量文件/数据处理下载文件归档、批量改名、表格汇总Python快捷指令数量少时跨设备内容联动手机写内容同步到 Mac快捷指令 iCloud 共享目录文件传输工具定时/位置触发每天准点抓页面、进 Wi-Fi 自动静音系统自动化/launchd快捷指令自动化旧软件无接口的操作只能靠菜单点击UI 模拟/AppleScript换成支持导出的新工具这张表不是一个金科玉律但能帮你少走弯路。核心逻辑就是能用官方接口、文件交换、数据导出去解决的事就不要用模拟点击能用轻工具解决的就不要上重脚本。3.3 两个具体选型示例看两个真实例子你就知道怎么用了。例一一个做编辑的朋友每天要把网站上十几条行业动态整理成一张表格字段是日期、标题、来源、链接数量不大但天天重复。这个任务我给他的方案是快捷指令起步读取网页内容按分隔符拆成列表逐条写入表格。十几条数据量级不大快捷指令完全扛得住改起来也直观。如果哪天数据量涨到几百条再换成 Python 遍历抓取也不迟。例二另一个朋友每周要从三个后台分别导出三份 Excel做去重合并再算几个统计字段最后发邮件。这明显是批量加工类快捷指令做不了我直接建议 Python openpyxl跑完后自动生成汇总表邮件那一步留人工确认。这两个例子说明同一个道理路线不是越高越好而是越贴合数据规模越好。4. 四类高频场景的落地脚本与踩坑记录选型说完了下面放四个我实际写过的自动化片段覆盖刚才提到的三类需求。代码可以直接抄但每个场景后面我都会配一段踩坑记录那才是大多数人第一次运行后真正会遇到的问题。4.1 下载目录按月归档这个场景非常典型每天下载的东西全堆在“下载”文件夹里乱成一锅粥。方案是 Python 脚本按文件名里的日期没有日期就按修改时间归档到按月目录。from pathlib import Path import re import shutil from datetime import datetime download_dir Path.home() / Downloads target_root Path.home() / Downloads / 归档 for item in download_dir.iterdir(): if not item.is_file(): continue if item.name.startswith(.) or item.name 归档: continue m re.search(r(\d{4})-(\d{2})-(\d{2}), item.name) if not m: mtime datetime.fromtimestamp(item.stat().st_mtime) month mtime.strftime(%Y-%m) else: month f{m.group(1)}-{m.group(2)} target_dir target_root / month target_dir.mkdir(parentsTrue, exist_okTrue) target_path target_dir / item.name if target_path.exists(): suffix datetime.now().strftime(%H%M%S) target_path target_dir / f{item.stem}_{suffix}{item.suffix} shutil.move(str(item), str(target_path))第一次跑这个脚本系统会弹权限提示“允许访问下载文件夹吗”这是 macOS 的隐私保护机制得点允许。如果没弹窗就去系统设置里的“隐私与安全性—文件与文件夹”手动加权限很多新人卡在这一步。脚本里我特意忽略了隐藏文件和归档目录本身不然它会把自己的老窝也搬走。另一个坑是重名文件目标月份里已经有同名文件时直接覆盖是不可接受的我加了自动加时间戳的处理。跑之前建议先复制一个小目录试跑别一上来就对整个下载目录动手。4.2 快捷指令清洗剪贴板这个场景更适合用快捷指令而不是 Python从网页复制带格式的文本粘贴到文档里之前想清洗掉多余空行、超链接参数以及那些长得像脏代码的追踪字段。具体创建步骤打开快捷指令 App新建指令添加“获取剪贴板”添加“替换文本”开启“正则表达式”把三个以上连续换行替换成一个换行再添加一次“替换文本”把utm_*开头的链接参数清掉添加“拷贝到剪贴板”在快捷指令详细信息里绑定菜单栏或快捷键。要注意的是快捷指令里的正则是 ICU 语法和 Python 的 re 略有差异写复杂规则前先拿样例文字跑一遍。替换之前最好先加一步“显示结果”看看清洗效果对了再把预览这步删掉。直接覆盖剪贴板的话原内容丢了就很难找回来了。我因为没做预览曾经把一整篇带排版的重要原文洗成了纯文本等于白改了一次。4.3 用 openpyxl 把多张 Excel 汇总成一张每周要合并多份导出表格的人应该不少。下面这段代码加载一张“账单.xlsx”按分类字段汇总金额再写出一张新的汇总表。要注意它只是示意真实场景建议先把所有明细表放在同一个目录再用循环读取。import openpyxl from pathlib import Path from collections import Counter wb openpyxl.load_workbook(账单.xlsx) ws wb.active header [cell.value for cell in ws[1]] category_idx header.index(分类) amount_idx header.index(金额) counter Counter() for row in ws.iter_rows(min_row2, values_onlyTrue): if row[category_idx] is None: continue counter[row[category_idx]] float(row[amount_idx]) out openpyxl.Workbook() out_ws out.active out_ws.append([分类, 合计]) for category, total in counter.most_common(): out_ws.append([category, round(total, 2)]) out.save(汇总.xlsx)表格自动化最典型的坑有三个。第一是空值一行数据里分类字段为空直接跳过否则后面全崩。第二是金额格式可能是文本或者带货币符号转 float 之前要先清洗。第三是 openpyxl 保存的 xlsx 再交给 Numbers 打开时格式会被重排如果你的工作流终点是 Numbers建议同时输出一份 CSV 副本兜底。这个脚本我每周跑一次跑完只做复核运行很稳定。如果你需要更复杂的统计换成 pandas 处理起来更顺手但小场景用 openpyxl 已经足够了。4.4 用 launchd 定时抓取公开页面场景是每天上午 9 点半抓取某个公开信息页面的正文保存到本地方便有空再看。重点不是抓取本身而是怎么在 macOS 上设置定时任务。import requests from bs4 import BeautifulSoup url https://example.com/公开页面 headers {User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36} r requests.get(url, headersheaders, timeout15) r.raise_for_status() soup BeautifulSoup(r.text, html.parser) target soup.select_one(#main .content) text target.get_text(stripTrue) with open(页面快照.txt, w, encodingutf-8) as f: f.write(text)然后建一个 launchd 的 plist 放在~/Library/LaunchAgents/com.example.dailycheck.plist?xml version1.0 encodingUTF-8? !DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd plist version1.0 dict keyLabel/key stringcom.example.dailycheck/string keyProgramArguments/key array string/usr/bin/python3/string string/Users/你的用户名/Scripts/daily_check.py/string /array keyStartCalendarInterval/key dict keyHour/key integer9/integer keyMinute/key integer30/integer /dict keyStandardOutPath/key string/tmp/daily_check.log/string keyStandardErrorPath/key string/tmp/daily_check_error.log/string /dict /plistlaunchd 跑脚本和终端跑脚本有个非常坑的差异环境变量几乎是空的。这意味着你直接写python3可能找不到正确版本第三方库也可能 import 失败。解决办法是 plist 里的路径写绝对路径先用which python3确认路径再填进去。脚本里如果需要自己的模块也要显式sys.path.insert。还有 ProgramArguments 的执行文件路径不能省StandardErrorPath 必须写。我最早部署时少写了错误日志连续两天脚本没跑都不知道为什么后来排查才发现是 Python 命令路径写错了。另外加载任务用launchctl load查看日志直接打开对应 log 文件排查效率会高很多。顺手强调一句抓取公开页面时只碰允许访问的数据频率要克制不要高频请求去干扰对方服务器更不要去碰需要登录或者付费才能访问的内容。5. 写自动化脚本前必须先想清楚的三件事最后这部分不是我故意加戏而是踩坑攒出来的。很多人把脚本跑通一次就以为完事了之后不是这里权限过期就是那里路径变化最后维护成本高到放弃。写自动化之前先把这三件事想明白。5.1 权限与安全自动化会放大你的操作权限macOS 对文件夹、屏幕录制、辅助功能、日历通讯录这些敏感权限管控很严这是好事。但很多人为了图省事会去网上找“一键关闭隐私保护”之类的设置我强烈不建议。自动化脚本本质上是替你执行操作权限越大出错时的破坏力也越大。一个写文件权限给足的脚本一旦正则表达式写错可能批量把不该改的文件改了。我在脚本里做文件操作时会刻意加一个 dry_run 开关默认只打印不执行确认无误再开真跑。另外脚本里不要硬编码密码和密钥macOS 的钥匙串访问、环境变量都可以更安全地做这件事。还有一条铁律不要用自动化去对抗别人平台的防刷机制或隐私边界。自动化是提升自己设备效率用的不是用来薅别人的。5.2 异常处理脚本跑一半崩了你怎么知道我第一次写自动化脚本时完全没有日志概念脚本半夜崩溃第二天检查才发现数据少了。从那以后我给自己定了几条规矩。第一脚本入口就初始化一个本地日志文件每处理一个对象写一行状态。几百行日志看起来啰嗦但排查问题时是命根子。第二脚本要设计成可以重复执行不会因为中途崩溃产生重复数据最土的办法就是在处理前检查目标是否已存在。第三关键动作结束后发一个本地通知比如用 osascript 直接弹一个通知中心消息看到通知才放心。快捷指令里原理一样每个可能出错的动作后面接一个“如果出错则显示通知”的分支至少能让你知道卡在哪。日志写得越细致维护成本降得越低这是所有自动化项目里投入产出比最高的一件事。5.3 维护成本省下 10 分钟别用 2 小时去换算一笔账一个自动化每天帮你省 3 分钟一年约 18 小时看起来很不错。但如果它每一两周坏一次每次修要花 1 小时那这 18 小时还没捂热就赔进去了。所以选路线时要把维护成本也算进去。快捷指令改一个参数是秒级的很适合那些经常变来变去的轻任务。Python 脚本虽然写起来费点劲但逻辑一旦稳定反而可以稳定跑几个月不用动。我的习惯是做完一个自动化先跑两周观察期重点看它崩不崩、会不会产生重复数据观察期过了再放心交给它。每周一早上花十分钟查看所有定时任务最近几天的日志这十分钟是防止“悄悄失效”最有效的投资。自动化不是一锤子买卖它是你日常工作流的一部分维护是必须计入成本的。用了几年自动化下来我的最大感受是这东西真正值钱的地方不是让你看起来像个技术高手而是它从你的日常里抠出了几段完整的休息时间。我每天早上到工位下载文件夹已经整理完该抓取的数据已经躺在桌面了。要说有什么技巧也就一句话——先记录你今天重复做了什么再去选明天要用的路线。从最容易下手的那一个动作开始跑通了你自然就知道下一步该自动化什么了。