1.下载StandforCorenlp

Overview - CoreNLP  下载并解压。

根据语言进行选择,我这里选择的是English。下载并解压

解压完成后,将这两个文件放入到  ./stanford-corenlp-4.5.9文件夹下面。

2.安装StandforCornlp

配置虚拟环境,安装StandforCornlp,直接pip install,或者使用镜像‘

pip install stanfordcorenlp
pip install stanfordcorenlp -i http://pypi.mirrors.ustc.edu.cn/simple/ --trusted-host pypi.mirrors.ustc.edu.cn

3.数据集

4.测试

文件测试

file = './datasets/raw/semeval14/restaurant_test.raw'
with open(file, 'r') as file:
    data = file.readlines()
print(data[0].split('\t'))
print(data[1].split('\t'))
print(data[2].split('\t'))

依存关系解析测试

from stanfordcorenlp import StanfordCoreNLP
import re

# 初始化CoreNLP(确保路径正确)
nlp = StanfordCoreNLP(r'./stanford-corenlp-4.5.9')

# 原始句子和方面词信息(模拟raw格式输入)
raw_sentence = 'the entire staff was extremely accomodating and tended to my every need .'
aspect_terms = [{"term": "staff", "polarity": "postive"}]  # 从raw解析得到

# 获取基础数据
tokens = nlp.word_tokenize(raw_sentence)
pos_tags = [tag for _, tag in nlp.pos_tag(raw_sentence)]

# 获取依存关系并转换为目标格式
dependencies = nlp.dependency_parse(raw_sentence)

# 初始化head和deprel数组(长度=token数)
head = [0] * len(tokens)  # 默认父节点为0
deprel = ["root"] * len(tokens)  # 默认依存关系

# 转换依存关系到目标格式
for dep in dependencies:
    relation, gov_idx, dep_idx = dep
    current_idx = dep_idx - 1  # 转换为0-based索引

    # StanfordCoreNLP的根节点特殊处理
    if relation == "ROOT":
        head[current_idx] = 0
        deprel[current_idx] = "ROOT"
    else:
        # 父节点索引保持1-based(符合JSON格式)
        head[current_idx] = gov_idx
        deprel[current_idx] = relation.lower()

# 处理方面词位置
aspects_list = []
for aspect in aspect_terms:
    term = aspect["term"]
    polarity = aspect["polarity"]

    # 对方面词进行分词(确保与句子分词一致)
    term_tokens = nlp.word_tokenize(term)
    term_len = len(term_tokens)

    # 在tokens中查找匹配位置
    start_index = -1
    for i in range(len(tokens) - term_len + 1):
        # 比较token序列(不区分大小写)
        if tokens[i:i + term_len] == term_tokens:
            start_index = i
            break

    # 添加到aspects列表
    if start_index != -1:
        aspects_list.append({
            "term": term_tokens,
            "from": start_index,
            "to": start_index + term_len,  # 左闭右开区间
            "polarity": polarity
        })

# 构建最终JSON对象
json_data = {
    "token": tokens,
    "pos": pos_tags,
    "head": head,
    "deprel": deprel,
    "aspects": aspects_list
}

nlp.close()

# 打印验证结果
print("Tokens:", json_data["token"])
print("Head:", json_data["head"])
print("Deprel:", json_data["deprel"])
print("Aspects:", json_data["aspects"])

# 完整JSON输出(用于保存)
import json

print("\nComplete JSON:")
print(json.dumps(json_data, indent=2))

5.实现

import os
import json
from stanfordcorenlp import StanfordCoreNLP

# 初始化Stanford CoreNLP
nlp = StanfordCoreNLP(r'./stanford-corenlp-4.5.9')


def convert_polarity(polarity_str):
    """将数字极性转换为字符串标签"""
    polarity_map = {
        '1': 'positive',
        '0': 'neutral',
        '-1': 'negative'
    }
    return polarity_map.get(polarity_str.strip(), 'neutral')


def find_aspect_position(tokens, aspect_term):
    """在分词后的句子中查找方面词的位置"""
    term_tokens = nlp.word_tokenize(aspect_term)
    term_len = len(term_tokens)

    # 尝试精确匹配
    for i in range(len(tokens) - term_len + 1):
        if tokens[i:i + term_len] == term_tokens:
            return i, i + term_len

    # 尝试小写匹配(处理大小写不一致)
    lower_tokens = [t.lower() for t in tokens]
    lower_term = [t.lower() for t in term_tokens]
    for i in range(len(tokens) - term_len + 1):
        if lower_tokens[i:i + term_len] == lower_term:
            return i, i + term_len

    # 尝试去除标点匹配
    clean_tokens = [t.strip(".,!?;:'\"") for t in tokens]
    clean_term = [t.strip(".,!?;:'\"") for t in term_tokens]
    for i in range(len(tokens) - term_len + 1):
        if clean_tokens[i:i + term_len] == clean_term:
            return i, i + term_len

    # 如果仍然找不到,返回None
    return None, None


def process_line(line):
    """处理单行数据(包含三行信息)"""
    parts = line.strip().split('\t')
    if len(parts) != 3:
        return None

    raw_sentence, aspect_term, polarity = parts

    # 构建完整句子(替换$T$)
    full_sentence = raw_sentence.replace('$T$', aspect_term)

    # 获取基础数据
    tokens = nlp.word_tokenize(full_sentence)
    pos_tags = [tag for _, tag in nlp.pos_tag(full_sentence)]

    # 获取依存关系并转换为目标格式
    dependencies = nlp.dependency_parse(full_sentence)

    # 初始化head和deprel数组
    head = [0] * len(tokens)
    deprel = ["root"] * len(tokens)  # 默认值

    # 转换依存关系
    for dep in dependencies:
        relation, gov_idx, dep_idx = dep
        current_idx = dep_idx - 1  # 转换为0-based索引

        if relation == "ROOT":
            head[current_idx] = 0
            deprel[current_idx] = "ROOT"
        else:
            head[current_idx] = gov_idx
            deprel[current_idx] = relation.lower()

    # 处理方面词位置
    start_index, end_index = find_aspect_position(tokens, aspect_term)

    if start_index is None:
        print(f"Warning: Could not find aspect term '{aspect_term}' in sentence: {full_sentence}")
        return None

    # 构建JSON对象
    return {
        "token": tokens,
        "pos": pos_tags,
        "head": head,
        "deprel": deprel,
        "aspects": [{
            "term": nlp.word_tokenize(aspect_term),
            "from": start_index,
            "to": end_index,
            "polarity": convert_polarity(polarity)
        }]
    }


def convert_raw_to_json(input_path, output_path):
    """将原始数据文件转换为JSON格式"""
    if not os.path.exists(input_path):
        print(f"Error: Input file {input_path} not found")
        return

    # 修复编码问题:显式指定UTF-8编码
    with open(input_path, 'r', encoding='utf-8') as f:
        lines = f.readlines()

    # 每三行处理为一个样本
    json_data = []
    for i in range(0, len(lines), 3):
        if i + 2 >= len(lines):
            break

        # 合并三行数据为一个字符串表示
        combined_line = f"{lines[i].strip()}\t{lines[i + 1].strip()}\t{lines[i + 2].strip()}"
        result = process_line(combined_line)

        if result:
            json_data.append(result)
            print(result)

    # 保存结果,同样使用UTF-8编码
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(json_data, f, indent=2, ensure_ascii=False)  # ensure_ascii=False保留非ASCII字符

    print(f"Successfully converted {len(json_data)} samples to {output_path}")


# 执行转换
convert_raw_to_json('./datasets/raw/semeval16/restaurant_test.raw', './Restaurant16/test.json')

# 关闭CoreNLP连接
nlp.close()

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐