
关于“抢票脚本”这类需求这里必须先做一个口径说明绕过大麦、猫眼等票务平台的正常购流程批量抢票或高价代拍本质上属于绕过平台交易规则和反自动化限制的行为文章中不会提供任何相关代码或方案。这篇文章要解决的是同一个前提下的另一件事Python 自动化脚本怎么写、怎么跑、怎么稳定执行、怎么接入批量任务。这里的“自动化”可以理解为测试自己的业务系统、处理重复文件操作、巡检接口健康状态、定时跑报表任务。所有案例都能在本机自己搭环境复现不需要依赖大流量站点也不会触发平台风控。如果你刚接触 Python 自动化想找到一条“学完就能用到工程里”的路径那这篇文章很适合你。1. 核心能力速览能力项说明适用语言版本Python 3.10 及以上推荐 3.11/3.12典型用途接口自动化测试、浏览器操作自动化、批量文件处理、任务定时执行运行系统Windows 10/11、Linux、macOS硬件要求普通办公电脑即可不需要 GPU依赖组件Python、pip、venv必要时安装 Playwright 或 Selenium批量任务通过 requests 线程池或 pytest 参数化能够批量执行定时执行Windows 计划任务、systemd timer、crontabAPI 集成可对接企业微信、飞书、钉钉机器人发送结果通知入门成本会 Python 基础语法就能上手不需要机器学习基础从实际使用来看这条路线更偏向“自动化运维测试”和“RPA 方向”而不是去和高并发平台硬拼。先建立一套能复用的模板后续碰到新的自动化需求只是替换业务函数的问题。2. 适用场景和使用边界Python 自动化的常见场景有下面几类接口回归测试每天早上对内部系统的 20 个核心接口跑一遍检查响应码、响应时间、关键字段是否为空。浏览器流程测试模拟用户登录、下单、查询等操作验证页面功能是否正常。前提是你对被测系统有测试授权。批量文件处理把目录中的 csv 转 xlsx把一堆图片压缩改名按规则归档日志。数据巡检扫描配置文件检查数据库连接、磁盘空间和进程状态有异常就告警。定时执行任务每两个小时拉取一次外部数据做完清洗后写入本地数据库。边界问题同样重要不要用自动化去绕过任何网站的验证码、登录限制、风控策略。不要抓取需要授权才能访问的数据也不要对目标服务发起高频请求。涉及自己公司内部系统提前确认测试权限和窗口时间。涉及用户数据、密钥、Token脚本里不要硬编码推荐使用环境变量或配置文件。自动化只是把重复操作标准化它放大的是操作效率。如果操作本身没有授权放大出来的就是风险。3. Python 自动化脚本环境准备用最干净的方式准备环境不建议直接往系统 Python 里塞包。后面项目多了依赖冲突会非常难受。3.1 安装 PythonWindows 用户直接从 Python 官方下载安装包安装时勾选“Add Python to PATH”。安装完成后打开命令行验证python --version pip --version如果提示“不是内部或外部命令”说明 PATH 没有生效。重新打开命令行窗口或者在系统环境变量里手动加上 Python 安装目录和 Scripts 目录。3.2 建虚拟环境进入项目目录创建独立环境mkdir auto-project cd auto-project python -m venv venvWindows 激活环境venv\Scripts\activateLinux / macOS 激活环境source venv/bin/activate激活后命令行前面会多出(venv)前缀。后面安装的所有依赖都只在这个项目里生效。3.3 安装常用依赖第一个模板项目只需要两个依赖pip install requests pip install python-dotenv如果做浏览器自动化再加一个 Playwrightpip install playwright playwright install chromium也可以使用 Selenium需要额外下载浏览器驱动并确认版本匹配。Playwright 对新手更友好会自动管理对应浏览器版本后面示例会以它为主。4. 第一个可执行的 Python 自动化模板脚本直接给一个能跑通的模板。这里模拟的是一个“批量检测代理服务”场景只是举例换成你自己的业务函数即可。工程目录建议保持这样的结构auto-project/ │-- config.env │-- requirements.txt │-- main.py │-- utils/ │ ├-- __init__.py │ ├-- logger.py │ └-- checker.py └-- logs/4.1 统一日志模块日志是自动化的眼睛。建议一开始就配置好不要到处只写print。utils/logger.pyimport logging import os from logging.handlers import RotatingFileHandler LOG_DIR logs os.makedirs(LOG_DIR, exist_okTrue) def get_logger(name: str) - logging.Logger: logger logging.getLogger(name) logger.setLevel(logging.INFO) if not logger.handlers: formatter logging.Formatter( %(asctime)s - %(name)s - %(levelname)s - %(message)s ) console logging.StreamHandler() console.setFormatter(formatter) file_handler RotatingFileHandler( os.path.join(LOG_DIR, auto.log), maxBytes5 * 1024 * 1024, backupCount3, encodingutf-8, ) file_handler.setFormatter(formatter) logger.addHandler(console) logger.addHandler(file_handler) return loggerRotatingFileHandler的作用是日志超过 5MB 后自动切分保留最近 3 个文件避免日志无限增长撑爆磁盘。4.2 业务检测函数假设要检测一批服务的端口连通性用 Python 自带的socket实现utils/checker.pyimport socket from typing import Dict, List def check_tcp_port(host: str, port: int, timeout: float 3.0) - bool: 检测指定地址和端口是否可连接 try: with socket.create_connection((host, port), timeouttimeout): return True except OSError: return False def batch_check(targets: List[Dict]) - List[Dict]: results [] for target in targets: ok check_tcp_port(target[host], target[port]) results.append( { name: target[name], host: target[host], port: target[port], reachable: ok, } ) return results这是一个非常简洁的模板配置数据进入函数返回结构化结果日志只负责记录过程。以后不管业务多复杂都可以沿用这个模式。4.3 主函数入口main.pyimport json from utils.logger import get_logger from utils.checker import batch_check logger get_logger(main) def load_targets(path: str): with open(path, r, encodingutf-8) as f: return json.load(f) def main(): logger.info(自动化任务启动) # 从文件读入检测目标 targets load_targets(targets.json) logger.info(共读取到 %s 个检测目标, len(targets)) results batch_check(targets) failed [r for r in results if not r[reachable]] logger.info(检测完成失败 %s 个, len(failed)) for item in failed: logger.warning(%s 不可连接%s:%s, item[name], item[host], item[port]) # 把结果写回文件方便后续处理 with open(result.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: main()targets.json内容[ { name: 本地开发环境, host: 127.0.0.1, port: 8000 }, { name: 内部测试网关, host: 192.168.1.10, port: 8080 } ]运行方式python main.py只要看到日志中出现了“自动化任务启动”和“检测完成”说明整套模板已经跑通了。后面要处理更复杂的业务只需要替换batch_check背后的逻辑。5. Web界面自动化操作控制浏览器而不是抢资源浏览器自动化经常被误解成“模拟点击去抢某些资源”这不是它的设计初衷。Playwright / Selenium 的正确用法是在你拥有测试权限的网站上做自动化回归测试。下面以 Playwright 为例演示一个登录页面测试。先安装对应浏览器playwright install chromiumweb_test.pyfrom playwright.sync_api import sync_playwright def test_login(): with sync_playwright() as p: browser p.chromium.launch( headlessFalse, slow_mo300, ) page browser.new_page( viewport{width: 1280, height: 720} ) # 访问被测系统测试环境 page.goto(http://127.0.0.1:8080/login, timeout60000) # 填写登录表单 page.fill(#username, tester) page.fill(#password, 123456) # 点击登录按钮 page.click(button[typesubmit]) # 等待用户中心元素出现超时则抛出异常 page.wait_for_selector(#user-center, timeout10000) print(登录成功页面元素可见) browser.close() if __name__ __main__: test_login()很多项目第一版都会踩几个固定问题元素定位不到等下还有场景可能是因为内容异步加载需要用wait_for_selector或expect等待而不是直接操作。网络慢导致超时把超时时间放宽到 30 秒以上。弹窗/遮罩覆盖先关闭弹窗再执行下一步。headlessTrue时看不到页面调试阶段建议用headlessFalse加slow_mo500。这里说的“自动购票”类脚本技术上通常是基于类似浏览器自动化实现但它违反平台协议而且容易导致账号被冻结风险很高不建议研究这个方向。把同样的技能用在测试内部系统、优化工作效率上价值更大。6. 接口自动化与批量任务改造浏览器自动化适合用户操作流程接口自动化则负责一个更快的层面直接调用后端接口验证返回数据。用requests写一个简单接口巡检脚本api_check.pyimport requests from utils.logger import get_logger logger get_logger(api_check) API_BASE_URL http://127.0.0.1:8080/api TIMEOUT 10 def check_health() - bool: 检查服务健康接口 try: resp requests.get(f{API_BASE_URL}/health, timeoutTIMEOUT) if resp.status_code ! 200: logger.warning(健康检查返回非200%s, resp.status_code) return False data resp.json() if data.get(status) ! ok: logger.warning(健康检查状态异常%s, data) return False return True except requests.RequestException as exc: logger.error(健康检查请求失败%s, exc) return False def batch_check_endpoints(endpoints: list) - list: 对多个接口执行批量检测比较适合批量任务接管 results [] for endpoint in endpoints: url f{API_BASE_URL}{endpoint[path]} try: resp requests.get(url, timeoutTIMEOUT) results.append( { path: endpoint[path], status_code: resp.status_code, elapsed_ms: round(resp.elapsed.total_seconds() * 1000, 2), } ) except requests.RequestException as exc: results.append( { path: endpoint[path], error: str(exc), } ) return results if __name__ __main__: targets [ {path: /health}, {path: /api/v1/version}, {path: /api/v1/config}, ] result batch_check_endpoints(targets) for item in result: logger.info(接口巡检结果%s, item)为了让执行效率更高可以把串行请求改成线程池。import concurrent.futures from api_check import check_health def run_with_thread_pool(endpoints, max_workers4): with concurrent.futures.ThreadPoolExecutor(max_workersmax_workers) as executor: future_map { executor.submit(check_health): endpoint for endpoint in endpoints } for future in concurrent.futures.as_completed(future_map): endpoint future_map[future] try: is_ok future.result() print(f{endpoint[path]} - {OK if is_ok else FAIL}) except Exception as exc: print(f{endpoint[path]} - EXCEPTION {exc})控制并发数很重要不要一上来就开 100 个线程去打别人接口。接口巡检面对的是自己有权限调用的内部系统正常并发控制在 4~8 个即可。超过 20 个线程可能先把你自己的机器资源占满。pytest 也是接口自动化里的常见工具。你把上面的results变成 pytest 的测试断言后就能在 CI/CD 里集成def test_health(): assert check_health() is True后续可以用pytest-html生成测试报告用allure-pytest生成更直观的看板但这已经属于测试框架层面今天先把脚本跑通再说。7. 定时调度与无人值守脚本写好后不能每次都手动跑。下面给两种最常用的调度方式。7.1 Windows 计划任务假设 Python 脚本路径是D:\auto-project\main.py创建run_task.batecho off cd /d D:\auto-project call venv\Scripts\activate.bat python main.py然后在 Windows 搜索“任务计划程序”新建任务触发器设置每天 08:00 运行操作选择执行run_task.bat。启动主程序之前先cd到项目目录这一步很容易漏。如果不切换目录脚本里的相对路径会找不到targets.json和logs目录。7.2 Linux crontabcrontab -e加入任务0 8 * * * cd /home/user/auto-project /home/user/auto-project/venv/bin/python main.py /home/user/auto-project/logs/cron.log 21注意这里直接调用虚拟环境里的 python避免使用系统 Python 导致依赖加载错误。7.3 任务执行后的通知批量任务最怕无人值守时静默失败。简单做法是用企业微信机器人或飞书机器人发送一个结果摘要。import requests def send_webhook(webhook_url: str, content: str): payload { msgtype: text, text: { content: content, }, } response requests.post(webhook_url, jsonpayload, timeout10) response.raise_for_status()Webhook 地址放在config.env中不要写死在代码仓库里WEBHOOK_URLhttps://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyxxxx读取方式import os from dotenv import load_dotenv load_dotenv() webhook_url os.getenv(WEBHOOK_URL, )这样即使脚本被放到公共仓库密钥也不会泄露。8. 资源占用与性能观察自动化脚本的硬件门槛很低但长期跑还是需要注意内存和文件句柄。观察一个 Python 进程的资源占用import os import psutil pid os.getpid() process psutil.Process(pid) memory_mb process.memory_info().rss / 1024 / 1024 print(f当前进程 PID: {pid}) print(f内存占用: {memory_mb:.2f} MB)一个普通 requests 脚本内存占用通常在 30~80MB 之间。如果你发现脚本运行半小时后内存涨到 500MB 以上先检查是不是在循环里积累日志或把大文件持续读入内存。批量任务的资源观察重点是并发数并发 1 ~ 4适合读写文件、调用内部接口。并发 8 ~ 16适合耗时在 0.5 秒以上且相互独立的网络请求。并发超过 32除非接口明确支持高并发否则会明显增加失败率。如果任务对响应速度要求不高建议采用“串行 一次性重试”的保守方案。跑批类任务稳定优先快那几分钟意义不大。再给一个接口耗时统计的通用装饰器import functools import time from utils.logger import get_logger logger get_logger(timer) def log_runtime(func): functools.wraps(func) def wrapper(*args, **kwargs): start time.perf_counter() result func(*args, **kwargs) elapsed time.perf_counter() - start logger.info(%s 耗时 %.3f 秒, func.__name__, elapsed) return result return wrapper耗时这个指标在自动化里非常重要。如果某天任务跑得特别久第一个该查的就是哪一步耗时被拉长了。9. 常见问题与排查方法问题现象可能原因排查方式解决方案提示python不是内部或外部命令Python 未安装或未加入 PATHecho %PATH%查看路径重新安装并勾选 Add Python to PATHpip安装包超时默认源在国外网络不稳定查看错误信息中的超时地址切换到国内镜像源虚拟环境激活后没有(venv)前缀激活命令执行失败直接运行python --versionWindows 使用venv\Scripts\activateLinux 使用source venv/bin/activatePlaywright 报浏览器未安装只安装了 playwright 包没装浏览器运行playwright install chromium安装对应浏览器页面元素定位不到前端异步加载或 iframe打开浏览器开发者工具检查元素改用wait_for_selector如果有 iframe 先切换 frame接口返回 403缺少 Cookie/Token 或触发风控查看响应头信息和服务端日志确认请求身份信息完整不要在无授权情况下高频访问批量任务跑着跑着卡住某个请求没有设置超时点击任务查看正在请求的 URL所有 requests 都加timeout参数日志文件越来越大缺少日志轮转查看 logs 文件夹大小改用RotatingFileHandler定时任务执行但没效果工作目录不对在脚本第一行打印当前目录定时任务里先cd /d 项目目录最经典的坑有三个第一所有网络请求都要设置timeout。不设超时意味着一个连接挂起任务就会卡在那里。严重时线程池里所有线程都被占用整个任务看起来就像死机了。第二定时任务里的相对路径。手动运行在项目目录中没问题定时任务启动时的工作目录可能是C:\Windows\System32这时候logs目录会创建到系统目录里去。最稳妥的做法是在脚本入口处用绝对路径from pathlib import Path BASE_DIR Path(__file__).resolve().parent LOG_DIR BASE_DIR / logs TARGET_FILE BASE_DIR / targets.json第三批量任务的失败重试要放在业务层面。比如连接失败时重试 3 次每次间隔 1 秒而不是直接抛异常。import time MAX_RETRY 3 def request_with_retry(url, timeout10): for attempt in range(1, MAX_RETRY 1): try: response requests.get(url, timeouttimeout) return response except requests.RequestException: if attempt MAX_RETRY: raise time.sleep(1)10. 最佳实践与后续路线自动化脚本能不能长期稳定运行不在于技术多高级而在于工程习惯。下面是几条可以直接套用的经验。先用最小命令验证再写完整模块。第一次部署到新环境时先跑一个只打印 Python 版本和项目目录的脚本确认环境没问题再跑完整任务。一下子上全套报错后反而分不清是环境问题还是代码问题。项目目录分层。配置放config/脚本入口放项目根目录公共工具放utils/输出结果放output/日志统一放logs/。不要所有文件都堆在根目录下。配置不写死。URL、端口、账号、Token 全部放到配置文件或环境变量。代码只负责读取配置不允许在业务代码里硬编码上线环境地址。任务加结果汇报。只输出到控制台等于没有输出尽量让结果落盘或推送到工作群。这样第二天打开群消息就知道昨晚任务跑了没跑、哪些成功哪些失败。失败重试要有退避时间。失败后立即重试通常还是会失败。比较合适的策略是失败后先等 1 秒、再等 2 秒、再等 5 秒最多重试 3 次。边界和授权先确认。不管目标是网页表单、内部接口还是文件目录先回答两个问题我有没有权限对它做自动化操作操作频率是否会影响到其他使用者这两个问题没想清楚前别急着写代码。到这里你已经具备了一套可复用的 Python 自动化脚本能力环境配置、统一日志、文件读取、Web 自动化、接口巡检、批量任务、定时调度、异常排查。后面再扩展无非是加业务模块。把今天这套模板保存好遇到新需求直接往utils目录里添加模块而不是每次重新写入口。这也是“脚本”和“小型自动化工程”的分水岭。