指可扩展标记语言(eXtensible Markup Language)。 被设计用来传输和存储数据。而HTML被用来显示数据。
是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。
Python对 解析有三种方式:SAX,DOM,以及ElementTree。
SAX (simple API for )
python 标准库包含SAX解析器,SAX用事件驱动模型,通过在解析 的过程中触发一个个的事件并调用用户定义的回调函数来处理 文件。
DOM(Document Model)
将 数据在内存中解析成一个树,通过对树的操作来操作 。
ElementTree(元素树)
ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
注:因DOM需要将 数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取 文件,比较快,占用内存少,但需要用户实现回调函数。本文使用用ElementTree方式,以名称规范档的下载文本为例。
在ElementTree中,具体节点的方法主要包括
tag(标签) attrib(属性) find(寻找节点) set(设置属性) iter(遍历节点) get(获取节点)
解析
from .etree import ElementTree as ET
#第一种方式
# 打开文件,读取 内容
str_ = open(\'xo. \', \'r\').read()
# 将字符串解析成 特殊对象,root代指 文件的根节点
root = ET. (str_ )
from .etree import ElementTree as ET
#第二种方式
# 直接解析 文件
tree = ET.parse(\"xo. \")
# 获取 文件的根节点
root = tree.getroot()
操作
遍历 文档的所有内容
from .etree import ElementTree as ET
# 直接解析 文件
tree = ET.parse(\"test. \")
# 获取 文件的根节点
root = tree.getroot()
### 操作
# 顶层标签
print(root.tag)
# 遍历 文档的第二层
for child in root:
# 第二层节点的标签名称和标签属性
print(child.tag, child.attrib)
# 遍历 文档的第三层
for i in child:
# 第二层节点的标签内容
print(i.text)
遍历 中指定的节点
from .etree import ElementTree as ET
# 直接解析 文件
tree = ET.parse(\"test. \")
# 获取 文件的根节点
root = tree.getroot()
# 顶层标签
print(root.tag)
# 遍历 中所有的属性名节点
for node in root.iter(\'属性名\'):
# 节点的标签名称和内容
print(node.text)
修改节点内容
解析中,要注意修改或者写出 文件都是在内存中进行,如果要在文件中保存修改,要使用tree的write()方法。set()可设置属性,remove()可删除制定节点,例:
# 直接解析 文件
tree = ET.parse(\"xo. \")
# 获取 文件的根节点
root = tree.getroot()
############ 操作 ############
# 顶层标签
print(root.tag)
# 循环所有的year节点
for node in root.iter(\'year\'):
# 将year节点中的内容自增一
new_year = int(node.text) + 1
node.text = str(new_year)
# 设置属性
node.set(\'name\', \'alex\')
node.set(\'age\', \'18\')
# 删除属性
del node.attrib[\'name\']
############ 保存文件 ############
tree.write(\"newnew. \", encoding=\'utf-8\')
创建 文档
方式一
from .etree import ElementTree as ET
# 创建根节点
root = ET.Element(\"famliy\")
# 创建节点大儿子
son1 = ET.Element(\'son\', {\'name\': \'儿1\'})
# 创建小儿子
son2 = ET.Element(\'son\', {\"name\": \'儿2\'})
# 在大儿子中创建两个孙子
grandson1 = ET.Element(\'grandson\', {\'name\': \'儿11\'})
grandson2 = ET.Element(\'grandson\', {\'name\': \'儿12\'})
son1.append(grandson1)
son1.append(grandson2)
# 把儿子添加到根节点中
root.append(son1)
root.append(son1)
tree = ET.ElementTree(root)
tree.write(\'oooo. \',encoding=\'utf-8\', short_empty_elements=False)
方式二
from .etree import ElementTree as ET
# 创建根节点
root = ET.Element(\"famliy\")
# 创建大儿子
# son1 = ET.Element(\'son\', {\'name\': \'儿1\'})
son1 = root.makeelement(\'son\', {\'name\': \'儿1\'})
# 创建小儿子
# son2 = ET.Element(\'son\', {\"name\": \'儿2\'})
son2 = root.makeelement(\'son\', {\"name\": \'儿2\'})
# 在大儿子中创建两个孙子
# grandson1 = ET.Element(\'grandson\', {\'name\': \'儿11\'})
grandson1 = son1.makeelement(\'grandson\', {\'name\': \'儿11\'})
# grandson2 = ET.Element(\'grandson\', {\'name\': \'儿12\'})
grandson2 = son1.makeelement(\'grandson\', {\'name\': \'儿12\'})
son1.append(grandson1)
son1.append(grandson2)
# 把儿子添加到根节点中
root.append(son1)
root.append(son1)
tree = ET.ElementTree(root)
tree.write(\'oooo. \',encoding=\'utf-8\', short_empty_elements=False)
方式三
from .etree import ElementTree as ET
# 创建根节点
root = ET.Element(\"famliy\")
# 创建节点大儿子
son1 = ET.SubElement(root, \"son\", attrib={\'name\': \'儿1\'})
# 创建小儿子
son2 = ET.SubElement(root, \"son\", attrib={\"name\": \"儿2\"})
# 在大儿子中创建一个孙子
grandson1 = ET.SubElement(son1, \"age\", attrib={\'name\': \'儿11\'})
grandson1.text = \'孙子\'
et = ET.ElementTree(root) #生成文档对象
et.write(\"test. \", encoding=\"utf-8\", _declaration=True, short_empty_elements=False)
名称规范档文本
名称规范档没有提供批量下载同一人物的接口,在数据量大的实验需求中,设计实现了处理批量文本的方法。
首先,在下载的同一文档中包含不同ID号的多条人物数据,分别以 开头,以结尾,因此第一步,逐行读取文本,匹配结尾标识符“\\n”,匹配成功则将先前读取的 文档写出到新的文件,并给与新的命名以区别不同文本,实现代码如下:
def file_seperate(file_path,to_path):
for fileName in os.listdir(file_path):
f1 = open(file_path+\"/\"+fileName,\'r\',encoding=\"utf-8\")
# print(file_path+\"/\"+fileName)
text = \"\"
num = 1
for content in f1.readlines():
text += content
if \"</collection>\"+\"\\n\" == content:
num_str = str(num)
f2 = open(to_path + \"/0\" + num_str + fileName ,\'w\',encoding=\"utf-8\")
f2.write(text)
f2.close()
text = \"\"
num = num + 1
f1.close()
解析结果可得(以沈从文为例)01沈从文. 、02沈从文. 、03沈从文. ,进一步分析,在每一篇 文件,要获取具体属性值构建目标文本集,为进一步的数据处理提供依据。根据研究需要,获取 文件中的collection>>record>>datafield>>subfield字段,并限定具体属性的subfield字段,如{\'code\': \'a\'}、{\'code\': \'f\'}、 {\'code\': \'3\'}、{\'code\': \'u\'},循环读取进行匹配,匹配成功则构建新的目标文本,与原文本同名。实现代码如下:
def _parse(file_path,Target_path):
for fileName in os.listdir(file_path):
file = file_path+\"/\"+fileName
text = \'\'
tree = ET.parse(file)
root = tree.getroot()
for node in root:
for node_node in node:
if node_node.attrib == {\'tag\': \'200\', \'ind1\': \' \', \'ind2\': \'0\'} or node_node.attrib =={\'tag\': \'400\', \'ind1\': \' \', \'ind2\': \'0\'} or node_node.attrib =={\'tag\': \'810\', \'ind1\': \' \', \'ind2\': \' \'} or node_node.attrib =={\'tag\': \'830\', \'ind1\': \' \', \'ind2\': \' \'} or node_node.attrib =={\'tag\': \'856\', \'ind1\': \'4\', \'ind2\': \' \'}:
for subfield in node_node:
if subfield.attrib == {\'code\': \'a\'} or subfield.attrib == {\'code\': \'f\'} or subfield.attrib == {\'code\': \'3\'} or subfield.attrib == {\'code\': \'u\'}:
text = text + subfield.text
print(text)
f = open(Target_path+\"/\"+fileName,\'w\',encoding=\'utf-8\')
f.write(text)
f.close()
主函数如下,分别设定原始路径,处理文件路径,目标文件路径:
if __name__ == \"__main__\":
path_Source = \"D:/study/name_cluster/test/test02/data-Source\"
path_Separate = \"D:/study/name_cluster/test/test02/data-Separate\"
path_Target = \"D:/study/name_cluster/test/test02/data-Target\"
file_seperate(path_Source,path_Separate)
_parse(path_Separate,path_Target)
继续阅读与本文标签相同的文章
可视化你的BLAST结果
-
虚拟主机有什么优、缺点?
2026-05-19栏目: 教程
-
服务注册
2026-05-19栏目: 教程
-
服务器被攻击 如何查找漏洞以及攻击手法
2026-05-19栏目: 教程
-
Spring Cloud Zuul的动态路由怎样做?集成Nacos实现很简单
2026-05-19栏目: 教程
-
springboot自动配置原理
2026-05-19栏目: 教程
