在做Aspect-level情感分类时一般会用到SemEval 2014数据集。官网给的数据集都是XML格式,我们要对其进行解析。
首先看一下数据结构。
一个XML文件里包含多个sentence,每个sentence里包含text、aspectCategories和aspectTerms子节点,即我们需要提取出来的内容。
下面是代码。
首先,导入库。
import xml.etree.cElementTree as ET
Python标准库中,提供了ElementTree的两种实现。一个是纯Python实现的xml.etree.ElementTree,另一个是速度更快的C语言实现的xml.etree.cElementTree。第二种速度更快,而且内存消耗较少。
接下来读文件,获取根节点。
path = 'data/restaurants-trial.xml'
tree = ET.parse(path)
root = tree.getroot()
子节点是嵌套的,我们可以通过索引访问特定的子节点。
如:
root[0][0].text
输出是第一个sentence中text节点的内容。
然后获取XML中的元素,保存到数组中即可。
获取aspectCategory
data = []
for sentence in root.findall('sentence'):text = sentence.find('text').textaspectCategories = sentence.find('aspectCategories')for aspectCategory in aspectCategories.findall('aspectCategory'):category = aspectCategory.get('category')polarity = aspectCategory.get('polarity')data.append((text, category, polarity))
Element.findall(): 只找到带有标签的元素,该标签是当前元素的直接子元素。
Element.find() :找到第一个带有特定标签的子元素。
Element.text:访问标签的内容
Element.get():访问标签的属性值
也可以转化成dataframe,保存到csv文件里。
df=pd.DataFrame(data,columns=['text','category','polarity'])
df.to_csv('data/data.csv',sep=' ')
df.head()
提取aspectTerms
提取aspectTerms和提取aspectCategories有一点不同,即并不是每个sentence都有aspectTerms节点,因此我们不能直接查找所有sentence的aspectTerms节点。那么解决方法是什么呢。这里就要用到强大的xpath表达式了,’.//aspectTerms/…'的含义是选择所有包含aspectTerms的sentence节点,其中“//”表示从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。“…”表示选择当前节点的父节点。
data=[]
for sentence in root.findall('.//aspectTerms/..'):text = sentence.find('text').textaspectTerms=sentence.find('aspectTerms')for aspectTerm in aspectTerms.findall('aspectTerm'):term = aspectTerm.get('term')polarity = aspectTerm.get('polarity')data.append((text, term, polarity))df = pd.DataFrame(data,columns=['text', 'term', 'polarity'])
df = df[df['polarity'].isin(['positive', 'negative', 'neutral'])]
df['polarity'] = df['polarity'].map({
'positive': 1, 'neutral': 0, 'negative': -1})df.to_csv('data/aspect_term.csv', sep=' ',index=0)
df