python
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, concat_ws, explode, split, coalesce, lit
from pyspark.sql.types import StringType
spark = SparkSession.builder.appName("InvalidCharacterFinder").getOrCreate()
# 假设已存在DataFrame df
# df = ...
# 获取所有字符串类型列名
string_columns = [f.name for f in df.schema.fields if isinstance(f.dataType, StringType)]
result = []
if string_columns:
# 处理空值并合并字符串列
non_null_cols = [coalesce(col(c), lit("")).alias(c) for c in string_columns]
combined_df = df.select(non_null_cols).select(concat_ws("", *string_columns).alias("merged_str"))
# 拆分字符并过滤空字符串
chars_df = combined_df.withColumn("char", explode(split(col("merged_str"), "")))\
.filter(col("char") != "")
# 定义合法字符集合
allowed_chars = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!'
'"#$%&\'()*+,-./:;<=>?@[]^_`{|}~')
# 收集非法字符并去重
unique_invalid = chars_df.rdd.map(lambda x: x.char)\
.filter(lambda c: c not in allowed_chars)\
.distinct()\
.collect()
# 按首次出现顺序保留字符(分布式环境无法保证绝对顺序)
seen = set()
ordered_result = []
for char in unique_invalid:
if char not in seen:
ordered_result.append(char)
seen.add(char)
result = ordered_result
print("非法字符集合:", ''.join(result))
代码说明:
- 数据准备:通过DataFrame Schema识别所有字符串类型的列
- 空值处理 :使用
coalesce
函数将NULL转换为空字符串,确保后续字符串合并有效 - 列合并 :使用
concat_ws
将多个字符串列的值合并为单个字符串 - 字符拆分:通过split+explode将字符串拆分为单个字符,并过滤空字符
- 非法字符过滤:使用RDD操作过滤不在白名单中的字符,并通过distinct去重
- 结果处理:使用有序集合保持字符首次出现的顺序(注意:分布式环境下无法保证绝对顺序)
注意事项:
- 最终结果字符顺序可能与实际数据中的出现顺序不完全一致
- 白名单包含94个可打印ASCII字符(排除空格和控制字符)
- 使用RDD操作提升分布式处理性能
- 最终结果字符串可能包含各类特殊符号、中文、表情符号等非标准ASCII字符