1. 规范行
如图所示,2295#才是真正第2295行内容,再看2333行,这一行其实根本不是完整的问答对,只是上一行内容的一部分。为了以后读取每一行问答对不出错,于是我决定先将这些行规范一下,鉴于此类有问题的行数很多,毕竟有接近8w条问答对,于是使用以下代码进行处理:
elements = ()
for i in range(1, 72290):#我一共有72289条数据,循环末尾加一
elements += (f"{i}#",) # 注意逗号,这里创建一个只有一个元素的元组
with open('QA数据72289条.txt', 'r', encoding = "utf-8") as input_file, open('output.txt', 'w', encoding = "utf-8") as output_file:
for line in input_file:
if line.startswith(elements):
# 当前行的开头是以数字#开头的
output_file.write(line)
else:
# 当前行的开头不是以数字#开头的
output_file.seek(0, 2) # 将文件指针移动到文件末尾
output_file.write(line.rstrip('\n')) # 去掉行末的换行符并写入文件末尾
使用以上代码可以规范绝大部分行,可是不知道哪里出了问题,又出现了如下图的问题:
莫名其妙在某一行的开头又出错了,虽然很少,但确实有一些!这一些需要我手动去改,但我不知道在哪些行有,我总不能再去逐行看吧,于是用以下代码检查哪些行不是以1234567890这十个数字开头的,返回它所在的行数:
def find_lines_without_digits(filename):
# 打开文件,读取每一行
with open(filename, 'r') as f:
lines = f.readlines()
# 记录不以数字开头的行数
line_numbers = []
for i, line in enumerate(lines):
if not line.strip().startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')):
line_numbers.append(i+1)
# 返回不以数字开头的行数
return line_numbers
filename = 'output.txt'
line_numbers = find_lines_without_digits(filename)
print(line_numbers)
一输出,尼玛还有这么多行?!不过好在总比不知道在哪些行强,这样有了行数在vscode右下角直接输入行数就可跳转到对应行去修改:
我在检查这些行的时候,偶然发现有的行开头确实是数字,但是不是行的序号,如下图28391行,于是重新修改查找代码:
with open('output.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if not line.startswith(str(i+1)+'#'):
print(f"Line {i+1}")
这样检查每一行的开头是否是该行数+“#”,如果不是,就会返回给我它的行数,比上一个方法严谨一些。
2. 对行中内容做修改
with open('output.txt', 'r', encoding = 'utf-8') as old_file, open('output1.txt', 'w', encoding = 'utf-8') as new_file:
for line in old_file:
new_line = line.split('#', 1)[1].strip() + '\n'
new_file.write(new_line)
运行上述代码将每一行中开头的数字加#删掉,并把纯内容逐行写到新文本中。
看起来没那么赘余了。
在每一行中,第一个@和#之间的内容是“经发问人采纳”的意思,对QA问答对来说毫无作用,因为都是这个,所以想将这些东西去除掉,并且在@前边是问题,#后边是回答,所以我要在问题和回答之间加个分隔符。
以下是使用Python读取txt文档中的每一行,删除第一个“@”和第一个“#”及其中间所有的内容,用一个“《answer》”代替此位置,并将新内容写入新的txt文档中的代码:
# 打开原始文档和新文档
with open('output1.txt', 'r', encoding = 'utf-8') as f, open('output2.txt', 'w', encoding = 'utf-8') as new_file:
# 逐行读取原始文档
for line in f:
# 找到第一个 "@" 和第一个 "#" 的位置
at_pos = line.find("@")
hash_pos = line.find("#")
# 如果存在 "@" 和 "#",并且 "@" 在 "#" 之前
if at_pos != -1 and hash_pos != -1 and at_pos < hash_pos:
# 将 "@" 和 "#" 之间的内容替换为 "《answer》"
new_line = line[:at_pos] + "《answer》" + line[hash_pos+1:]
else:
# 如果不存在 "@" 和 "#",或者 "@" 在 "#" 之后,则不进行替换
new_line = line
# 将处理后的行写入新文档中
new_file.write(new_line)
看起来又更顺眼了一点!
但是我红框中的内容其实也是些无意义的内容:
类似于点赞转发评论数量一样,于是我也想连这些数字和前边的点评二字一并删除。
思路就是读取txt文档的每一行,将每行中最后一个“དཔྱད་བརྗོད།”字符及其后边的字符删掉,并将这一行剩余的部分写入新txt文档的新一行中,代码如下:
# 打开原始文件和目标文件
with open('output2.txt', 'r', encoding = 'utf-8') as infile, open('output3.txt', 'w', encoding = 'utf-8') as outfile:
# 逐行读取原始文件并处理每行
for line in infile:
# 删除每行中最后一个"དཔྱད་བརྗོད།"及其后面的字符
line = line.rstrip() # 删除行末空格和换行符
line = line[:line.rfind('དཔྱད་བརྗོད།')] # 删除最后一个"###"及其后面的字符
# 将处理后的行写入目标文件
outfile.write(line + '\n')
处理之后,好嘛,确实看起来更简洁了,因为我发现有的根本就没有答案,只有问题!
但是也有很多问题和答案都有的:
这样其实每一行就只是问题+《answer》分隔符+答案了。
3. 总结
数据预处理到这里基本就结束了,剩下的部分等到在存储进数据库时,再做说明吧!
后边按照老师的要求应该会搭一个问答系统放在网页上,老师也让我再学一下知识表示的内容,听起来还很有意思呢!到时候会再进行记录~