当前位置:   article > 正文

Python 分析样例|文本整理案例:《全唐诗》文本整理_全唐诗txt 写入python字典

全唐诗txt 写入python字典

在整理《全唐诗》的文本之前,我们首先需要完成以下两个步骤:

  • 确定需求
  • 了解文本

在完成以上步骤后,我们开始实际着手整理文本,在整理的过程中大体上也包含两个流程:

  • 文本解析
  • 结果输出

全唐诗文本语料在“全唐诗.txt”文件中,请参考语料阅读以下内容。

确定需求

我们计划将《全唐诗》中的每一首诗的各种信息分别提取出来,并转存为csv的形式。根据对文本的初步了解,我们发现我们需要提取的信息(即绝大部分诗文都包含的共性信息)包括:

  • 诗文的所属的卷编号(后简称卷编号)
  • 诗文的在当前卷中的序号(后简称诗编号)
  • 诗文的标题
  • 诗文的作者
  • 诗文的内容

虽然有的诗并没有作者(例如卷899_19),但是在整体结构设计的时候不用考虑它们。

了解文本

在了解文本的过程中,主要围绕需要提取的信息的形式;通过了解文本,我们基本上得到可以解析大部分文本内容的规律性方法。

卷25_7【杂曲歌辞·侠客行】

李白

赵客缦胡缨,吴钩霜雪明。银鞍照白马,飒沓如流星。
十步杀一人,千里不留行。事了拂衣去,深藏身与名。
闲过信陵饮,脱剑膝前横。将炙啖朱亥,持觞劝侯嬴。
三杯吐然诺,五岳倒为轻。眼花耳热后,意气素霓生。
救赵挥金槌,邯郸先震惊。千秋二壮士,烜赫大梁城。
纵死侠骨香,不惭世上英。谁能书阁下,白首太玄经。


   卷106_7 【送金城公主适西蕃应制】郑愔 

下嫁戎庭远,和亲汉礼优。笳声出虏塞,箫曲背秦楼。 
贵主悲黄鹤,征人怨紫骝。皇情眷亿兆,割念俯怀柔。主
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

首先,通过了解我们发现每首诗的形式,都类似以上的形式。以一个标题行开始,标题行中基本上都包括卷编号和诗编号(卷[0-9]+_[0-9]+)和标题(【[^】]+】)两部分,有的时候也会包含作者名。因此,我们可以以标题行为标志,一旦发现标题行,就认为一首诗的内容已经结束,下一首诗的内容即将开始(即完成一首诗的整理)。

接着,通过仔细观察,我们发现标题行、诗文中偶尔会有多余的空格(包括半角或全角)出现,在诗文末尾还会有校注者知古斋主的标注。因此,对每一行我们需要进行初步的清洗,包括移除空格、换行符和校注者的标注((?<=[),。])[知古斋主]$)。

至此,我们已经可以提取出卷编号、诗编号、标题、内容这四部分,但是作者部分仍然存在一些问题。经过进一步的观察,我们发现当作者位于标题行时,作者名是除了卷编号、诗编号、标题以外的唯一的中文内容;当作者名存在于标题行之后的某一行中时,该行为不包含任何标点符号的一行。

此外,我们发现,卷的标题(“第一百六十三卷”、“卷一百六十四”等)、版权信息等内容也是非诗文的无效内容,我们也需要通过正则表达式等方法过滤掉它们。

文本解析

在对文本初步了解的基础上,我们可以实现对文本的解析。整体逻辑结构如下:按行遍历文本语料;若该行为标题行,则解析当前诗作信息;若该行非标题行,则将当前行的内容存入当前诗作的内容中。

在遍历的过程中,我们需要对各行的文本语料进行清洗,并过滤空行、无效行等。

在解析过程中,我们可以将解析的结果存储到list中,list中的每个元素为一首诗,每个元素包括卷编号、诗编号、标题、作者、内容五个属性。

读取文本语料

首先,按行读取txt格式的《全唐诗》文本语料。

with open("全唐诗.txt", encoding="UTF-8") as file:
    lines = file.readlines()
print("总行数:", len(lines))
  • 1
  • 2
  • 3
清洗文本语料

对每一行都进行的文本清洗:

line = line.replace("\n", "").replace(" ", "").replace(" ", "")
line = re.sub("卷[一二三四五六七八九十百]+", "", line)
line = re.sub("第[一二三四五六七八九十百]+卷", "", line)
  • 1
  • 2
  • 3

仅对文本内容行进行的文本清洗:

line = line.replace("¤", "。")  # 将错误句号替换为标准句号
line = re.sub("(?<=[),。])[知古斋主]$", "", line)  # 剔除校注者名称
  • 1
  • 2

过滤无效行(先文本清洗再过滤无效行,一遍将“第一百六十三卷”等过滤掉):

if "知古斋主精校" in line or "版权所有" in line or "web@guoxue.com" in line:
    continue
  • 1
  • 2
文本语料解析

在标题行中提取卷编号(Python 3.8+):

if book_regex := re.search("(?<=卷)[0-9]+(?=_)", line):
    book_num = int(book_regex.group())  # 读取卷编号
  • 1
  • 2

在标题行中提取诗编号(Python 3.8+):

if poem_regex := re.search("(?<=_)[0-9]+", line):
    poem_num = int(poem_regex.group())  # 读取诗编号
  • 1
  • 2

在标题行中提取标题(Python 3.8+):

if title_regex := re.search("(?<=【)[^】]+(?=】)", line):
    title = title_regex.group()  # 读取标题
  • 1
  • 2

在标题行中尝试提取作者(Python 3.8+):

line = re.sub("卷[0-9]+_[0-9]+", "", line)
line = re.sub("【[^】]+】", "", line)
if author_regex := re.search("[\u4e00-\u9fa5]+", line):
    author = author_regex.group()  # 如果作者名位于标题行,则为清除其他所有内容后剩余的中文
  • 1
  • 2
  • 3
  • 4

在非标题行中尝试提取作者:

if not re.search("[,。?!]", line):
	author_regex = re.search("[\u4e00-\u9fa5]+", line)
    author = author_regex.group()
  • 1
  • 2
  • 3

非标题行中的内容在清洗之后直接添加到诗文的内容中即可。

结果输出

在文本解析完成后,我们可以将存储在list中的临时数据存储到文件中。

with open("全唐诗(清洗后).txt", "w+", encoding="UTF-8") as file:
    for poem_item in poem_list:
        file.write(",".join([str(poem_item["卷编号"]), str(poem_item["诗编号"]), poem_item["标题"], poem_item["作者"],
                             poem_item["内容"]]) + "\n")
  • 1
  • 2
  • 3
  • 4

完整源代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/102198
推荐阅读
相关标签
  

闽ICP备14008679号