Airbnb房源数据清洗与整形:从CSV到可分析数据集的完整pandas流程

发布时间:2026/8/26 9:36:18

Airbnb房源数据清洗与整形:从CSV到可分析数据集的完整pandas流程
拿到一份 Airbnb Listings 数据很多人的第一反应是直接开始画图、跑模型结果一做特征分析就发现价格列带着$符号、评分大量缺失、同一套房源重复出现好几遍。本文就围绕 Airbnb 房源列表数据的清洗与整形整理一套从原始 CSV 到可直接分析的数据集完整流程包含代码示例、常见报错和工程习惯适合正在学习 pandas、准备做数据比赛或搭建数据分析项目的开发者。为了让过程可复现我会按“先体检、再清洗、后整形、再导出”的顺序讲解。你不需要额外准备数据库只要能跑 Python 和 pandas 就能跟着操作。1. 为什么要清洗和整形 Airbnb 房源数据1.1 什么是 Airbnb Listings 数据Airbnb Listings 数据简单说就是 Airbnb 平台上房源列表信息的汇总表。每条记录对应一套房源字段通常包含房源 ID、房源名称、房东信息、位置坐标、房间类型、可住人数、价格、评分、评论数、可预订天数等。这类数据在数据分析、城市研究、旅游推荐、价格预测等场景中非常常见。很多人会从公开渠道下载某个城市或区域的listings.csv文件然后基于它做分析。但公开数据并不等于“干净数据”恰恰相反它保留了真实业务数据里最常见的脏乱形态。1.2 原始数据常见问题把一份典型的 Airbnb listings 文件打开后你会遇到下面这些问题价格列是字符串例如$120.00带货币符号和千分位逗号不能直接求均值。浴室数量列是2.5 baths这类混合文本需要提取数字。last_review日期列可能是空值也可能是不同格式的日期字符串。host_is_superhost列是t/f这样的布尔文本不是 Python 的True/False。同一房源 ID 重复出现可能来自多次抓取或数据合并。大量列存在缺失值例如reviews_per_month对于没有评论的房源是空值。部分极端值例如价格为 0、可住人数为 0会影响统计结果。这些问题如果不处理后面的分组统计、透视表、可视化、机器学习建模都会出现偏差。1.3 清洗与整形的关系这里需要区分两个概念清洗Cleaning解决“数据不对”的问题包括缺失值、重复值、异常值、类型错误、格式不统一。整形Shaping解决“数据不方便用”的问题包括行列调整、字段拆分、类型转换、新增特征、分组汇总、透视转换。清洗是整形的前提整形是清洗后的下一步。大多数 pandas 教程会把它们混在一起讲但实际项目里最好按这个顺序推进先保证每条记录和每个字段是“对的”再把它变成“好用的”。本文的实战部分也采用这个流程。2. 环境准备与数据集说明2.1 运行环境与依赖本文代码基于 Python 3 环境核心依赖是 pandas 和 numpy。你可以用 pip 安装pip install pandas numpy版本需要根据你的项目实际情况调整本文示例以 pandas 1.5 / 2.x 的常见写法为例重点演示清洗与整形思路。如果你使用的是更早版本个别方法名可能有差异但整体流程一致。推荐使用 Jupyter Notebook 或 VS Code 的交互式窗口逐步执行方便分步查看每一阶段的数据形态。2.2 数据集字段说明为了演示效果下面以一份典型的 Airbnblistings.csv为例。真实数据可能列名略有不同但核心字段通常是这些字段名含义常见脏数据示例id房源唯一 ID重复记录name房源名称空白、乱码host_id房东 ID无host_name房东名称缺失neighbourhood_group区域组大小写混用latitude / longitude经纬度缺失或越界room_type房间类型空格、大小写不一致price每晚价格$120.00minimum_nights最少入住天数异常值 0number_of_reviews评论数缺失last_review最近评论日期字符串日期reviews_per_month每月评论数缺失availability_365一年可订天数缺失bathrooms_text浴室描述2.5 bathshost_is_superhost是否超赞房东t/f2.3 项目目录结构设计建议先建好目录把数据文件和脚本分离。这里有一个常见教训很多人把脚本、原始数据、输出结果全放在同一层目录开发到后面目录越来越乱甚至在不同路径之间复制文件时出现奇怪报错。一个朴素的目录结构如下airbnb_clean/ ├── data/ │ └── listings.csv ├── output/ │ └── airbnb_listings_clean.csv ├── scripts/ │ └── clean_listings.py └── notebooks/ └── 01_eda.ipynb在终端里创建目录时如果父目录不存在或权限不足会出现类似cannot mkdir的报错。这往往不是命令本身写错而是目录结构需要先理清要么提前创建好父目录要么检查当前用户是否有写权限。在 Python 脚本里更推荐使用pathlib的方式后面实战代码会给出。3. 核心方法拆解3.1 数据体检info、describe、dtypes拿到数据第一步不是清洗而是体检。pandas 提供了三个最基础的方法import pandas as pd df pd.read_csv(data/listings.csv) print(df.shape)df.shape查看行数和列数。df.info()查看每列的非空数量、数据类型是最快的缺失值扫描方式。df.describe(includeall)查看数值列和类别列的大致分布。执行完这三步你基本能判断哪些列需要重点处理。3.2 缺失值处理缺失值处理没有银弹核心思路是分列处理如果某列缺失比例过高且业务上不重要可以直接删除该列。如果缺失比例低可以选择填充常用中位数、均值、众数或固定值。如果缺失列是日期、评论等强相关字段可以结合业务规则填充例如没有评论的房源reviews_per_month填 0。判断缺失比例可以这样写missing df.isna().mean().sort_values(ascendingFalse) print(missing[missing 0])isna()返回布尔表mean()计算每列缺失比例按降序输出后一眼就能看出哪些列是“缺失大户”。3.3 重复值处理重复值要看业务含义完全重复的行可以直接删除。更常见的是id重复但其他字段略有差异这时需要指定subset参数按 ID 去重。df.drop_duplicates(subset[id], keepfirst, inplaceTrue)keepfirst表示保留第一次出现的记录后面的重复记录删除。3.4 数据类型修正pandas 读入 CSV 后所有列默认按内容推断类型。遇到混合类型时经常出现明明应该是数字的列变成object。修正方式是用pd.to_numericdf[price] pd.to_numeric(df[price], errorscoerce)errorscoerce的意思是能转成数字就转不能转的变成NaN。这样既不会因为个别脏数据中断程序也能在后续检查中看到哪些值有问题。3.5 字符串清洗字符串清洗通常处理四类问题去除首尾空格str.strip()统一大小写str.lower()/str.upper()替换或删除字符str.replace()提取子串str.extract()对于$120.00这样的价格可以先把货币符号和逗号去掉再转数值。对于2.5 baths可以用正则表达式提取小数部分。3.6 日期处理日期字段最常见的两个问题一是空值二是格式不统一。pandas 的pd.to_datetime能自动解析大部分常用日期格式df[last_review] pd.to_datetime(df[last_review], errorscoerce)一旦解析失败的值变成NaT日期列就是真正的datetime64类型后续可以做月份提取、天数计算等操作。4. 完整实战清洗并整形 Airbnb 房源表这一节我们把前面拆解的方法串成一个完整流程。建议新建一个脚本文件scripts/clean_listings.py每一段代码都可以独立运行也可以通过主函数串起来。4.1 创建项目目录并读取数据# 文件路径scripts/clean_listings.py from pathlib import Path import pandas as pd import numpy as np # 创建输出目录 BASE_DIR Path(__file__).resolve().parent.parent DATA_DIR BASE_DIR / data OUTPUT_DIR BASE_DIR / output OUTPUT_DIR.mkdir(parentsTrue, exist_okTrue) print(输出目录, OUTPUT_DIR)这里用exist_okTrue即使目录已经存在也不会报错。相比os.makedirs在目录已存在时抛FileExistsError这种方式更省心也避免了 shell 里cannot mkdir这类因目录冲突导致的报错。读取数据df pd.read_csv( DATA_DIR / listings.csv, na_values[, N/A, NA], ) print(原始数据形状, df.shape)na_values可以把常见空字符串统一识别为缺失值避免后续清洗时漏掉。4.2 第一步数据体检print(df.info())运行后会看到类似下面的输出列数会根据真实数据变化RangeIndex: 5000 entries, 0 to 4999 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 5000 non-null int64 1 name 4930 non-null object 2 price 4970 non-null object 3 room_type 5000 non-null object 4 bathrooms_text 4800 non-null object ...可以明显看到price是object而不是数值name、bathrooms_text都有缺失。接下来查看数值分布和缺失比例print(df.describe(includeall)) missing_ratio df.isna().mean().sort_values(ascendingFalse) print(missing_ratio[missing_ratio 0])4.3 第二步处理缺失值这一步的策略是先删再填。先删除缺失严重且业务价值不高的列# 这些列如果缺失率过高直接删除 cols_to_drop [license, neighborhood_overview] df df.drop(columns[c for c in cols_to_drop if c in df.columns])对缺失率较低但有明确业务含义的列做填充# 没有评论的房源每月评论数填 0 df[reviews_per_month] df[reviews_per_month].fillna(0) # 评分缺失用中位数填充避免极端值影响 df[review_scores_rating] ( df[review_scores_rating].fillna(df[review_scores_rating].median()) ) # 房间描述缺失可以先填 Unknown 或暂时保留 df[name] df[name].fillna(Unknown)对于last_review日期列如果没有最近评论实际上不应该随意填一个假日期。更合理的做法是把日期解析后结合number_of_reviews判断评论数为 0 的房源把last_review保留为缺失在后续分析中单独处理即可。df[last_review] pd.to_datetime(df[last_review], errorscoerce)4.4 第三步处理重复值先统计完全重复的行print(完全重复行数, df.duplicated().sum()) df df.drop_duplicates()再看id层面的重复print(按 id 去重前的行数, len(df)) df df.drop_duplicates(subset[id], keepfirst) print(按 id 去重后的行数, len(df))很多真实场景里完全重复的行并不多但id重复很常见。按id去重后数据集的唯一性就有了保障。4.5 第四步修正字段类型与格式价格列清洗df[price] ( df[price] .astype(str) .str.replace($, , regexFalse) .str.replace(,, , regexFalse) .str.strip() ) df[price] pd.to_numeric(df[price], errorscoerce) print(df[price].describe())这里先把价格统一转成字符串再清洗避免个别行是数字时直接调用str方法报错。regexFalse表示把$当作普通字符替换不做正则匹配。浴室数量提取df[bathrooms] ( df[bathrooms_text] .astype(str) .str.extract(r([\d.])) .astype(float) ) df[bathrooms] pd.to_numeric(df[bathrooms], errorscoerce)str.extract(r([\d.]))会从2.5 baths中提取2.5从1 bath中提取1。布尔字段转换df[host_is_superhost] df[host_is_superhost].map( {t: True, f: False, T: True, F: False} )如果转换后仍有NaN说明原始数据里存在其他值可以打印检查print(df[host_is_superhost].value_counts(dropnaFalse))房间类型统一小写并去除空格df[room_type] ( df[room_type].astype(str).str.strip().str.lower() ) print(df[room_type].value_counts())4.6 第五步整形与特征塑造当基础字段都干净之后就可以进入“整形”阶段。常见的整形操作包括筛选、排序、分组、透视和新增特征。先剔除明显异常的记录df df[ df[price].between(10, 2000) df[accommodates].between(1, 16) ].copy()copy()很重要它避免后续修改触发SettingWithCopyWarning这类 pandas 警告。新增“人均价格”特征df[price_per_person] ( df[price] / df[accommodates].replace(0, np.nan) )把accommodates为 0 的情况先替换成NaN避免除零错误。新建价格区间列bins [0, 100, 200, 500, 10000] labels [经济型, 舒适型, 高端型, 豪华型] df[price_level] pd.cut( df[price], binsbins, labelslabels, rightFalse, )分组统计不同房型的房源数量、均价和评分room_summary ( df.groupby(room_type, as_indexFalse) .agg( 房源数(id, count), 平均价格(price, mean), 中位价格(price, median), 平均评分(review_scores_rating, mean), ) .sort_values(房源数, ascendingFalse) ) print(room_summary)如果数据里有neighbourhood_group字段还可以做房型和区域的交叉透视pivot pd.pivot_table( df, indexneighbourhood_group, columnsroom_type, valuesprice, aggfuncmedian, ) print(pivot.head())透视表很适合观察“哪个区域的哪种房型贵”这类问题。4.7 第六步导出清洗结果清洗完成后的数据导出为新的 CSV 文件output_path OUTPUT_DIR / airbnb_listings_clean.csv df.to_csv(output_path, indexFalse, encodingutf-8-sig) print(已保存, output_path)encodingutf-8-sig是为了让 Excel 打开 CSV 时不会出现中文乱码是中文项目里的实用习惯。5. 常见问题与排查思路在清洗 Airbnb 数据时最容易遇到下面这些问题问题现象常见原因解决思路启动脚本提示cannot mkdir父目录不存在、权限不足或目录已存在使用Path.mkdir(parentsTrue, exist_okTrue)或先检查目录与权限pd.read_csv报ParserError文件编码不对、CSV 引号不闭合指定encodingutf-8或enginepython价格列转数值后出现大量NaN清洗规则没覆盖特殊格式例如$1,200.00的去逗号顺序不对先用str.replace去掉$和,再pd.to_numericstr.extract提取不到数字源数据格式与正则不匹配先value_counts()查看唯一值再调整正则SettingWithCopyWarning警告对切片后的 DataFrame 直接赋值在切片后调用.copy()日期解析后全是NaT日期字符串格式特殊或混入文本用errorscoerce保留可解析值再单独检查无法解析的样本删除缺失列后行列数对不上列名不存在却被drop用列表推导式[c for c in cols if c in df.columns]过滤排查思路建议按“数据体检 → 定位影响范围 → 先处理结构问题再处理内容问题 → 每步打印形状确认”的顺序进行。每次清洗操作后都打印一次df.shape能很快定位是哪一步改变了行数或列数。6. 最佳实践与工程建议6.1 保留原始数据清洗数据单独输出永远不要把清洗结果覆盖到原始 CSV 上。原始文件是数据资产的基线清洗脚本应该可以重复执行输出到独立目录。这样即使清洗规则写错了重新跑一遍脚本即可。6.2 清洗脚本要可复现把清洗过程写成函数而不是在 Notebook 里一个 Cell 一个 Cell 地敲。推荐拆成def load_data(path): ... def clean_missing(df): ... def clean_types(df): ... def shape_features(df): ... def main(): df load_data(...) df clean_missing(df) df clean_types(df) df shape_features(df) ...每个函数只做一件事方便单独测试和复用。6.3 用日志记录每一步项目规模变大后清洗步骤可能非常多。建议在关键节点打印或记录日志import logging logging.basicConfig(levellogging.INFO) logging.info(after load: %s, df.shape) logging.info(after dedup: %s, df.shape)这样跑完整个脚本你能清楚看到每一次操作的影响。6.4 谨慎处理缺失值填充缺失值不等于凭空造数据。填充前要问自己这个缺失是“业务上不存在”还是“数据采集失败”业务上不存在例如没有评论的房源reviews_per_month填 0 合理。数据采集失败不应该直接填均值建议先分析缺失原因。6.5 正则和类型转换要兜底errorscoerce不是偷懒而是让程序在遇到脏数据时继续运行并在后续检查中暴露问题。关键是转换后要抽样检查NaN确认没有把有效数据误判成缺失。6.6 大批量数据时注意内存Airbnb 城市级别的数据通常只有几万行内存压力不大。但如果你处理的是全国或全球级别的数据建议在读取时只选择需要的列cols [id, price, room_type, accommodates, number_of_reviews, review_scores_rating, last_review] df pd.read_csv(data/listings.csv, usecolscols)7. 总结与下一步通过本文的流程你应该已经掌握了 Airbnb Listings 数据清洗与整形的完整方法先识别数据问题再处理缺失值、重复值和类型错误最后通过分组、透视、特征工程把数据变成适合分析和建模的形态。这套流程不仅适用于 Airbnb 数据换到商品列表、用户画像、订单流水等场景思路完全一致。接下来你可以继续学习三块内容可视化分析用 matplotlib 或 seaborn 查看不同房型、不同区域的价格分布。异常值检测用 IQR 或机器学习方法识别价格、评论数中的异常值。价格预测建模把清洗后的数据应用到线性回归或树模型预测房源价格。实际项目中优先关注缺失值处理和类型一致性这两步直接影响后续所有分析的准确性。建议你找一份真实的 Airbnb 数据把本文每个步骤都手动跑一遍遇到报错就对照常见问题表格排查很快就能把清洗流程建立成自己的标准模板。如果本文对你有帮助可以收藏备用也欢迎在评论区交流你在清洗 Airbnb 数据时遇到的其他坑。

相关新闻

FPGA信号发生器:基于DDS的可编程数字信号源设计

FPGA信号发生器:基于DDS的可编程数字信号源设计

2026/8/26 9:36:18

1. 这不是玩具,是能进实验室的信号源——FPGA信号发生器到底解决了什么问题? 你有没有在调试一个ADC电路时,手头只有个几十块的函数发生器,调个20MHz正弦波就失真严重,想测谐波抑制比根本没法看;或者在验证…

冲击地压危险预测:深部开采中的物理驱动建模方法

冲击地压危险预测:深部开采中的物理驱动建模方法

2026/8/26 9:36:18

1. 这不是一道数学题,而是一场地下千米的“压力体检” 五一建模比赛C题一出来,我翻到“煤矿深部开采冲击地压危险预测”这个标题时,手里的咖啡顿了一下——这根本不是传统意义上套公式、调参数的建模题,它背后站着的是真实矿井里每…

VMware安装Windows Server 2008 R2:经典系统虚拟化部署与优化指南

VMware安装Windows Server 2008 R2:经典系统虚拟化部署与优化指南

2026/8/26 9:26:17

1. 项目概述:为什么今天还要折腾Windows Server 2008? 如果你点开了这篇文章,心里可能带着一丝疑惑:都202X年了,Windows Server 2008(尤其是R2版本)不是早就停止主流支持了吗?为什么…

天然气水合物资源量评价的地质建模逻辑与不确定性量化

天然气水合物资源量评价的地质建模逻辑与不确定性量化

2026/8/26 10:26:20

1. 这道题到底在考什么:从“天然气水合物”到“资源量评价”的真实建模逻辑 2024年数维杯C题的标题里藏着三个关键信息点: 天然气水合物、资源量评价、数学建模 。但很多同学一看到“天然气水合物”,第一反应是查百度百科,抄一段…

从零构建定制Linux内核与系统镜像:嵌入式开发与系统裁剪实战

从零构建定制Linux内核与系统镜像:嵌入式开发与系统裁剪实战

2026/8/26 10:26:20

1. 项目概述与核心价值 最近在折腾一个嵌入式项目,需要为一块特定的开发板定制一个轻量级的Linux系统。官方的Ubuntu Server镜像虽然方便,但内核版本固定,驱动支持不全,还带了一堆我用不上的服务和软件包,占用了宝贵的…

可持续智能建筑怎么落地?从Planet、People到Profits的系统实践

可持续智能建筑怎么落地?从Planet、People到Profits的系统实践

2026/8/26 10:26:20

1. 先看清这个标题在说什么:三个P不是口号 干这行这么多年,我最怕听到有人说"可持续建筑就是多装几块太阳能板"。真正的可持续智能建筑,从来不是单点技术的堆砌,而是一套把环境、人、钱三个维度同时考虑进去的系统工程。…

从Claude Code后门事件看AI编码助手安全风险与Coco协作范式

从Claude Code后门事件看AI编码助手安全风险与Coco协作范式

2026/8/26 10:26:20

1. 从“Claude Code后门事件”看AI协作工具的信任危机最近,AI编程助手领域出了件不大不小的事,让不少开发者心里咯噔了一下。一个名为“Claude Code”的工具被曝出存在安全后门。这事儿听起来有点技术八卦的味道,但背后折射出的,其…

高光谱图像分类实战:从数据预处理到深度学习模型构建与调优

高光谱图像分类实战:从数据预处理到深度学习模型构建与调优

2026/8/26 10:26:20

1. 项目概述:从“看见”到“看懂”的飞跃 高光谱分类,听起来是个挺学术的词,但说白了,它就是让机器像经验丰富的专家一样,不仅能“看见”物体,更能“看懂”物体到底是什么。我们人眼看到的世界,…

YOLOv8+ByteTrack实时目标跟踪实战:训练、调参与嵌入式部署

YOLOv8+ByteTrack实时目标跟踪实战:训练、调参与嵌入式部署

2026/8/26 10:16:20

简介:在计算机视觉领域,目标检测与多目标跟踪是支撑智能视频分析的两大基石。YOLOv8作为高效实时检测器,以高精度和灵活部署著称;而ByteTrack则凭借独特的BYTE关联机制与卡尔曼滤波,在不引入额外ReID模型的前提下实现稳…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/26 1:50:39

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/26 1:49:16

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

Python random 模块常用函数详解:从入门到实战

Python random 模块常用函数详解:从入门到实战

2026/8/26 0:05:45

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

Hermes接入团队协作后,我推翻了三个效率假设

Hermes接入团队协作后,我推翻了三个效率假设

2026/8/26 0:05:45

聊《Hermes真能提效吗?先看流程里最慢的那一步》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要团队把 Hermes 接进项目三个月后,交付速度没有提升反而慢了。复盘后发现,最先…

免费AI大模型调教指南:打造专属网文写作助手

免费AI大模型调教指南:打造专属网文写作助手

2026/8/26 0:05:45

1. 先搞清楚“AI小说扩展模式”到底能帮你做什么如果你是一个刚开始写网文、或者卡在L3级别以下的作者,最头疼的可能是情节推进不下去、人物对话干瘪,或者世界观设定不够丰满。自己对着空白文档硬憋,效率很低。这时候,一个能理解你…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…