从XML生成spacy的训练数据

0 投票
1 回答
43 浏览
提问于 2025-04-13 17:47

我有一些XML格式的数据,长得像这样:

<item n="main"><anchor type="b" ana="regO.lemID_12" xml:id="TidB13" />Stuttgart<anchor type="e" ana="reg0.lemID_12" xml:id="TidE13" /> d. 20. Sept [19]97<lb/>Lieber Herr Schmidt!<lb/>Ich bin sehr glücklich über die Aufnahme <anchor type="b" ana="regW.lemID_17" xml:id="TidB22" />meines <anchor type="b" ana="regP.lemID_4" xml:id="TidB4" />Shakespeare<anchor type="e" ana="regP.lemID_4" xml:id="TidE4" /><anchor type="e" ana="regW.lemID_17" xml:id="TidE22" /> bei euch, vielen Dank.</item>

我想把这些文本用作spacy的训练数据,所以我需要把它转换成spacy要求的格式:

doc = nlp("Laura flew to Silicon Valley.")
gold_dict = {"entities": [(0, 5, "PERSON"), (14, 28, "LOC")]}
example = Example.from_dict(doc, gold_dict)

特别是关于创建偏移量,也就是实体的开始和结束位置,我还是搞不清楚。有没有什么特别合适的方法来处理这个?

编辑:这是我到目前为止用ElementTree尝试的结果:

from xml.etree import ElementTree as ET

data = '''
<root>
<item n="main"><anchor type="b" ana="regO.lemID_12" xml:id="TidB13" />Stuttgart<anchor type="e" ana="reg0.lemID_12" xml:id="TidE13" /> d. 20. Sept [19]97<lb/>Lieber Herr Schmidt!<lb/>Ich bin sehr glücklich über die Aufnahme <anchor type="b" ana="regW.lemID_17" xml:id="TidB22" />meines <anchor type="b" ana="regP.lemID_4" xml:id="TidB4" />Shakespeare<anchor type="e" ana="regP.lemID_4" xml:id="TidE4" /><anchor type="e" ana="regW.lemID_17" xml:id="TidE22" /> bei euch, vielen Dank.</item>
</root>
'''
def get_entity_type(ana):
    if 'regO' in ana:
        return 'PLACE'
    if 'regP' in ana:
        return 'PERSON'
    if 'regW' in ana:
        return 'WORK'
    if 'regP' in ana:
        return "PERIODICA"
 
root = ET.fromstring(data)
print(root)
#text = ""
entities = []
current_pos = 0

for node in root.iter():
    #print(node)
    if node.tag == "anchor" and node.get('type')=='b':
        start_pos = current_pos
        ana = node.get('ana')
        entity_type = get_entity_type(ana)
        #print(entity_type)
    elif node.tag == "anchor" and node.get('type')=='e':
        entities.append((entity_type, start_pos, current_pos))       
                    
#print (entities)

所以抓取实体类型是可以的,但我想要抓取实体的开始和结束位置的想法是错的。我也尝试用pawpaw来做,像这里描述的那样。但它总是找不到"Ito"

这是我用pawpaw尝试的:

from pawpaw import ito
root = ET.fromstring(data)
elements = root.findall('.//')
print(elements)

for e in elements:
    plain_text = e.Ito.find('*[d:text]')
#     print(plain_text)

1 个回答

1

要提取你需要的文本,首先要找到元素 .tail

import xml.etree.ElementTree as ET

xml_str ="""
<item n="main"><anchor type="b" ana="regO.lemID_12" xml:id="TidB13" />Stuttgart<anchor type="e" ana="reg0.lemID_12" xml:id="TidE13" /> d. 20. Sept [19]97<lb/>Lieber Herr Schmidt!<lb/>Ich bin sehr glücklich über die Aufnahme <anchor type="b" ana="regW.lemID_17" xml:id="TidB22" />meines <anchor type="b" ana="regP.lemID_4" xml:id="TidB4" />Shakespeare<anchor type="e" ana="regP.lemID_4" xml:id="TidE4" /><anchor type="e" ana="regW.lemID_17" xml:id="TidE22" /> bei euch, vielen Dank.</item>
"""
root = ET.fromstring(xml_str)

text = []
for elem in root.iter():
    if elem.tail is not None:
        # with linebreak \n
        text.append(elem.tail+'\n')
        
t = ''.join(text)
print(t)
print(repr(t))

输出结果:

Stuttgart
 d. 20. Sept [19]97
Lieber Herr Schmidt!
Ich bin sehr glücklich über die Aufnahme 
meines 
Shakespeare
 bei euch, vielen Dank.

'Stuttgart\n d. 20. Sept [19]97\nLieber Herr Schmidt!\nIch bin sehr glücklich über die Aufnahme \nmeines \nShakespeare\n bei euch, vielen Dank.\n'

撰写回答