数据表的清洗分析

前言 re.sub函数的介绍

re.sub 是 Python 中 re 模块(正则表达式模块)提供的一个函数,用于在字符串中查找匹配正则表达式的子串,并将其替换为指定的字符串。下面是 re.sub 函数的参数和语法的详细介绍:

1.语法 re.sub(pattern, repl, string, count=0, flags=0) 2.参数

pattern (str 或 Pattern 对象):

正则表达式的模式,可以是字符串形式,也可以是预编译的正则表达式对象(通过 re.compile() 生成的)。

repl (str 或 函数):

替换的字符串(也可为一个函数)。如果是一个字符串,则其中的反斜杠转义字符(如 \n,\t 等)会被处理。如果是一个函数,则这个函数会被调用,每次匹配时传入一个匹配对象,然后返回要替换的字符串。

string (str):

要进行搜索和替换的原始字符串。

count (int, 可选):

模式匹配后替换的最大次数,默认为 0,表示替换所有的匹配。

flags (int, 可选):

控制正则表达式的匹配方式,如:是否忽略大小写,多行匹配等。可以是多个标志位的按位或组合。常见的标志位有:

re.IGNORECASE 或 re.I:忽略大小写。

re.MULTILINE 或 re.M:多行模式,改变 ^ 和 $ 的行为。

re.DOTALL 或 re.S:让 . 匹配包括换行符在内的所有字符。

re.VERBOSE 或 re.X:启用详细模式,可以写多行正则表达式,空白字符将被忽略,并且允许添加注

一.role_talent 1.源码 import pandas as pd import re #处理第一列函数 def clean_role(text): text = re.sub(r':.*', '', text) return text #清晰文本函数 def clean_dragon_description(text): # 去除文本两端的空格和换行符 text = text.strip() # 使用正则表达式去除多余的空格和换行符(保留段落间的单个换行符) text = re.sub(r'\s+', ' ', text) # 将多个空格替换为一个空格 text = re.sub(r'\n{2,}', '\n', text) # 将两个或更多换行符替换为一个换行符 # 去除逗号、句号和分号等前后的空格和换行符(适用于中文标点符号) text = re.sub(r'[ \n]*([,。;:])[ \n]*', r'\1', text) # 空格前后若有标点符号,则把空格改成空字符 text = re.sub(r'(?<=[,。;::!])\s+|\s+(?=[,。;::!])', '', text) # 删除紧挨着中文字符的空格(前后都是中文字符的情况) text = re.sub(r'(?<=[\u4e00-\u9fff])\s+(?=[\u4e00-\u9fff])', ',', text) # 将多个连续存在的标点符号替换为单个逗号(注意:这里假设只处理中文标点符号) # 注意:这个正则表达式应该放在去除单个标点符号前后空格和换行符之后 # 否则,连续的标点符号之间的空格和换行符会影响匹配结果 text = re.sub(r'[,,:.。;;!!;:·]{2,}', ',', text) # 将两个或更多中文标点符号替换为逗号 text = re.sub(r':', '是:', text) #在:前加“是” # 返回清洗后的文本 return text # 读取Excel文件 file_path = r'D:\python object\爬虫\原神爬取内容\role_talent.xlsx' # 请替换为你的Excel文件路径 sheet_name = 'genshin_talents_info' # 请替换为你的工作表名称 df = pd.read_excel(file_path, sheet_name=sheet_name) # 从第二行(索引为1)开始修改Column2的值,把Column1(索引从1开始)的内容字符串 # 拼接“的” # 再拼接原本的Column2的内容(索引从1开始) # 赋值给Column2,即可得到新的Column2内容 df.loc[1:, 'Column2'] = df.loc[1:, 'Column1'] + '的' + df.loc[1:, 'Column2'] # 对'Column2'列中的每个文本执行清洗操作 df['Column2'] = df['Column2'].apply(clean_dragon_description) # 从第二行(索引为1)开始修改Column1的值,即获取Column2的内容并应用clean_role函数得到特定内容 df.loc[1:, 'Column1'] = df.loc[1:, 'Column2'] .apply(clean_role) # 从第二行(索引为1)开始修改Column1的值,为其加上中文“什么?” df.loc[1:, 'Column1'] = df.loc[1:, 'Column1'] + '什么?' # print(df.to_string()) # 将清洗后的数据写回到Excel文件中(覆盖原文件) df.to_excel(file_path, sheet_name=sheet_name, index=False) # # 保存处理后的数据到新的Excel文件 # df.to_excel('processed_role_talent_with_format.xlsx', index=False) 2.代码解析 处理文本思路

        原始数据:

1.clean_dragon_description函数:把连续的空格变成一个空格,(将两个或更多换行符替换为一个换行符),再去除逗号、句号和分号等前后的空格和换行符(适用于中文标点符号)使内容之间没有空格,再删除紧挨着中文字符的空格(前后都是中文字符的情况),再将两个或更多中文标点符号替换为逗号。上述操作可以使内容间没有空格,且用逗号连接起来。再筛选内容的‘:’字符,在其前面添加“是”这个文字。

2.clean_role函数:目的是筛选‘:’这个字符后面的所有内容,把它替换为空,即删除:’这个字符后面的所有内容,这样只会保留Column2列‘:’这个字符前面的所有内容

3.Column2列:从第二行(索引为1)开始修改Column2的值,把Column1(索引从1开始)的内容字符串,拼接“的”,(上面第一列的内容即是:"基尼奇的")再拼接原本的Column2的内容(索引从1开始)赋值给Column2,即可得到新的Column2内容;再执行clean_dragon_description处理内容

Column2列内容: 基尼奇的天赋1(普通攻击)是:普通攻击,进行至多三段的连续攻击。通过元素战技「悬猎·游骋高狩」进行空中摆荡后,在落地之前能在空中进行一次普通攻击。重击,消耗一定体力,向前方旋转地投出大剑攻击敌人。下落攻击,从空中下坠冲击地面,攻击下落路径上的敌人,并在落地时造成范围伤害。

4.Column1列:从第二行(索引为1)开始修改Column1的值,即获取Column2的内容并应用clean_role函数得到特定内容(Column2列‘:’这个字符前面的所有内容,上述例子获取的内容是“基尼奇的天赋1(普通攻击)是”这个字符串);再从第二行(索引为1)开始修改Column1的值,为其加上中文“什么?”即可得到想要的内容“基尼奇的天赋1(普通攻击)是什么?”

# 去除逗号、句号和分号前后的空格和换行符(适用于中文标点符号) text = re.sub(r'[ \n]*([,。;:])[ \n]*', r'\1', text)

正则表达式解析

原始字符串

r'...' 前缀 r 表示这是一个原始字符串,意味着在这个字符串中的反斜杠 \ 将被当作普通字符处理,而不是转义字符。这对于正则表达式来说是非常重要的,因为正则表达式中经常使用到反斜杠。

字符集合

[ \n]* 是一个字符集合,匹配零个或多个空格 ( ) 或换行符 (\n)。

[ ] 表示字符集合。

和 \n 分别表示空格和换行符。

* 表示前面的字符集合可以出现零次或多次。

捕获组

([,。;:]) 是一个捕获组,用于匹配并捕获中文标点符号:逗号(,)、句号(。)、分号(;)、冒号(:)。

() 表示捕获组。

[,。;:] 是包含这些中文标点符号的字符集合。

整体结构

r'[ \n]*([,。;:])[ \n]*' 将上述两部分组合起来,表示匹配以零个或多个空格或换行符开头,紧接着是一个中文标点符号,然后再以零个或多个空格或换行符结尾的字符串。

re.sub 函数的应用

在 re.sub(pattern, repl, string, ...) 函数中:

pattern 是上述解释的正则表达式。

repl 是替换内容,这里是 r'\1',表示用捕获组中的内容(即中文标点符号)替换整个匹配到的字符串。

string 是要处理的原始字符串 text。

解释

正则表达式 r'[ \n]*([,。;:])[ \n]*' 在 text 中查找所有匹配的模式。

对于每个匹配,它捕获中文标点符号,并用这个标点符号替换整个匹配到的字符串(包括前后的空格和换行符)。

结果是,所有中文标点符号周围的空格和换行符都被删除了,只保留了标点符号本身。

re.sub(r'(?<=[,。;::!])\s+|\s+(?=[,。;::!])', '', text)

功能:这个正则表达式用于替换在标点符号(中文标点符号和英文冒号、感叹号)前后出现的空格。它确保标点符号前后没有不必要的空格。

正则表达式解析

(?<=[,。;::!]):这是一个正向后查找(positive lookbehind)断言,表示匹配的位置前面必须是中文标点符号(逗号,句号,分号,冒号,感叹号)或英文的冒号或感叹号。

\s+:匹配一个或多个空格字符。

|:逻辑或(OR),表示匹配前面的模式或后面的模式。

\s+(?=[,。;::!]):这是一个正向查找(positive lookahead)断言,表示匹配的位置后面必须是中文标点符号或英文的冒号或感叹号,并且匹配位置前面有一个或多个空格。

替换操作

将匹配到的空格(即标点符号前后的空格)替换为空字符(即删除这些空格)。

re.sub(r'(?<=[\u4e00-\u9fff])\s+(?=[\u4e00-\u9fff])', ',', text)

功能:这个正则表达式用于替换两个中文字符之间的空格,将空格替换为中文逗号

正则表达式解析

(?<=[\u4e00-\u9fff]):这是一个正向后查找断言,表示匹配的位置前面必须是一个中文字符(Unicode 范围在 \u4e00 到 \u9fff 之间)。

\s+:匹配一个或多个空格字符。

(?=[\u4e00-\u9fff]):这是一个正向查找断言,表示匹配的位置后面必须是一个中文字符。

替换操作

将匹配到的空格(即两个中文字符之间的空格)替换为中文逗号(,)。

二. enemys_info 1.源码 import re import pandas as pd def clean_dragon_description(text): # 去除文本两端的空格和换行符 text = text.strip() # 使用正则表达式去除多余的空格和换行符(保留段落间的单个换行符) text = re.sub(r'\s+', '', text) # 将一个或以上空格替换为无,即去除全部空格 return text # 读取Excel文件 file_path = r'D:\python object\爬虫\原神爬取内容\enemys_info.xlsx' # 请替换为你的Excel文件路径 sheet_name = 'enemys_info' # 请替换为你的工作表名称 df = pd.read_excel(file_path, sheet_name=sheet_name) # 对'Column2'列中的每个文本执行清洗操作 df['Column2'] = df['Column2'].apply(clean_dragon_description) # 将清洗后的数据写回到Excel文件中(覆盖原文件) df.to_excel(file_path, sheet_name=sheet_name, index=False) # 如果不希望覆盖原文件,可以将清洗后的数据保存到一个新文件中 # df.to_excel('cleaned_file.xlsx', sheet_name='Sheet1', index=False)

这里仅做了去除空格操作,不再赘述

三.weapons_info 1.源码 import re import pandas as pd def clean_dragon_description(text): # 第一步:清除内容之间的空格(包括标点符号周围的空格) text = re.sub(r'\s+', '', text) # 清除所有连续空格 # 第二步:在“·”后添加换行符 text = re.sub(r'·', r'\n·', text) # 返回清洗后的文本 return text # 读取Excel文件 file_path = r'D:\python object\爬虫\原神爬取内容\weapons_info.xlsx' # 请替换为你的Excel文件路径 sheet_name = 'weapons_info' # 请替换为你的工作表名称 df = pd.read_excel(file_path, sheet_name=sheet_name) # 对'Column2'列中的每个文本执行清洗操作 df['Column2'] = df['Column2'].apply(clean_dragon_description) # 将清洗后的数据写回到Excel文件中(覆盖原文件) df.to_excel(file_path, sheet_name=sheet_name, index=False) # 如果不希望覆盖原文件,可以将清洗后的数据保存到一个新文件中 # df.to_excel('cleaned_file.xlsx', sheet_name='Sheet1', index=False) 2.代码解析

因excel表中会出现武器效果名称不是单独一行的效果,因此对其进行以下处理:

思路是先去除内容的所有空格,筛选内容的“·” 标点符号,因其与小数点.不是一个字符,因此简单很多,直接匹配“·”这个字符,替换为"./n"即可达到以下效果

这里仅介绍两个正则表达式含义

正则表达式:r'\s+'

\s:代表空白字符,这包括空格、制表符(Tab)、换行符(\n)、回车符(\r)等所有表示空白的字符。

+:表示前面的字符(这里是\s,即空白字符)可以连续出现一次或多次。

替换内容:''(空字符串)

作用:这个正则表达式会查找文本中所有连续的一个或多个空白字符,并将它们替换为空字符串,即删除这些空白字符。

正则表达式:r'.'

:直接匹配文本中的“·”字符。

替换内容:r'\n.'

\n:代表换行符。

·:与正则表达式中匹配的字符相同,即“·”。

作用:这个正则表达式会查找文本中所有的“·”字符,并在每个“·”字符前插入一个换行符\n。即可让武器效果名称单独一行

 四.textmaps 1.源码 import re import pandas as pd def clean_dragon_description(text): # print(re.findall(r'【.*】', text)) # 第一步:清除内容之间的空格(包括标点符号周围的空格) text = re.sub(r'\s+', '', text) # 清除所有连续空格 # 第二步:删除【】及其包裹的内容(包括换行符) # 使用非贪婪匹配.*?和re.DOTALL标志来匹配换行符 text = re.sub(r'【.*?】', '', text, flags=re.DOTALL) # 返回清洗后的文本 return text # 读取Excel文件 file_path = r'D:\python object\爬虫\原神爬取内容\textmaps.xlsx' # 请替换为你的Excel文件路径 sheet_name = 'textmaps_info' # 请替换为你的工作表名称 df = pd.read_excel(file_path, sheet_name=sheet_name) # 对'Column2'列中的每个文本执行清洗操作 df['Column2'] = df['Column2'].apply(clean_dragon_description) # 将清洗后的数据写回到Excel文件中(覆盖原文件) df.to_excel(file_path, sheet_name=sheet_name, index=False) 2.代码解析  (1)懒惰匹配和贪婪匹配

在正则表达式中,【.*?】 这个模式用于匹配被中文全角左方括号 【 和中文全角右方括号 】 包围的内容,但匹配的内容是“非贪婪”的,即尽可能少地匹配字符。

这里的 .*? 是一个非贪婪匹配的量词,它修饰的是 . 这个特殊字符,. 在正则表达式中代表匹配除换行符之外的任意单个字符(如果在正则表达式中使用了 re.DOTALL 标志,则 . 也可以匹配换行符)。*? 表示非贪婪匹配,即尽可能少地匹配字符,只要满足整个模式的匹配条件就立即停止。

因此,【.*?】 会匹配文本中第一个出现的 【,然后非贪婪地匹配任意数量的任意字符(直到遇到第一个 】 为止),最后匹配 】。由于是非贪婪匹配,即使 】 之前有更多的字符可以匹配,正则表达式引擎也会在满足条件(即找到第一个 】)的情况下立即停止匹配。

(2)非贪婪匹配实例 

例如,考虑以下代码:

import re import pandas as pd def clean_dragon_description(text): #打印匹配到的所有字符串 print(re.findall(r'【.*?】', text)) # 第一步:清除内容之间的空格(包括标点符号周围的空格) text = re.sub(r'\s+', '', text) # 清除所有连续空格 # 第二步:删除【】及其包裹的内容(包括换行符) # 使用非贪婪匹配.*?和re.DOTALL标志来匹配换行符 text = re.sub(r'【.*?】', '', text, flags=re.DOTALL) # 返回清洗后的文本 return text # 示例文本(包含多个连续标点符号的例子) dragon_description = """ 【陈旧的手记】(扉页上大大咧咧地写着一个名字:沙法卡特)【陈旧的手记】「以前在教令院的时候,大家都客客气气地叫我老师或者先生。到了这里之后,就只有孩子们会拜访我的小屋,他们都叫我沙法卡特叔叔。」「境遇一变,人的称呼也会跟着变,让人感慨。村里也没人认识我,那我就舍弃学者的身份,心甘情愿去种地吧。」【陈旧的手记】「跟随自己的信念行动,我没有什么好后悔的,写下日记也不是为了自省。」「记得被驱逐到这里之前,我偷看了女儿的日记本。她生气地说谁看了她的日记,谁就会变成青蛙。呱,呱。我有点想念她。」 """ # 调用清洗函数 cleaned_description = clean_dragon_description(dragon_description) # 打印清洗后的文本 # print(cleaned_description)

输出结果:

(3)贪婪匹配实例 

改成

print(re.findall(r'【.*】', text))

 输出结果:

['【陈旧的手记】(扉页上大大咧咧地写着一个名字:沙法卡特)【陈旧的手记】「以前在教令院的时候,大家都客客气气地叫我老师或者先生。到了这里之后,就只有孩子们会拜访我的小屋,他们都叫我沙法卡特叔叔。」「境遇一变,人的称呼也会跟着变,让人感慨。村里也没人认识我,那我就舍弃学者的身份,心甘情愿去种地吧。」【陈旧的手记】']

解释:

正则表达式 re.findall(r'【.*】', text) 的目的是匹配所有被中文全角左方括号 【 和中文全角右方括号 】 包围的内容。然而,由于使用的模式是 .*(贪婪匹配),它会尽可能多地匹配字符,直到遇到最后一个可能的 】 为止,这通常会导致它跨越多个实际的 】 标记,从而匹配到比预期更长的字符串。

在示例文本中,第一个 【陈旧的手记】 之后紧接着是文本和另一个 【陈旧的手记】,而没有中间的闭合 】 来结束第一个匹配。因此,.* 会继续匹配,直到它遇到下一个 【 之前的最后一个 】,但这实际上并不是第一个 【 的配对闭合 】。由于贪婪匹配的特性,它会忽略中间的 】,并尝试匹配尽可能多的字符。

使用正则表达式 re.search(r'【.*?】', text)(或者如果你想匹配所有这样的内容,可以使用 re.findall(r'【.*?】', text))可以找到第一个被 【 和 】 包围的内容,即 【里面包含了需要提取的短内容】。如果你使用了 re.findall,则会找到所有匹配的内容,包括 【里面还有另一个需要提取的长内容,可能包含多行文本】。

注意,由于非贪婪匹配的特性,每次匹配都会尽可能少地包含字符,直到遇到第一个 】 为止。因此,即使 【 和 】 之间有大量的内容,每次匹配也只会包含到最近的 】 之前的所有内容。

2025-04-17 22:51 点击量:11