You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从PGN文件提取着法与注释:代码输出格式调整求助

调整PGN提取代码以匹配目标输出格式

现有代码提取国际象棋PGN文件的着法与注释时,输出格式不符合预期。预期格式示例:

1.d4 f5
The Dutch Defense
2.Nf3 e6 3.Nc3
Blocking his c-pawn, White aims for rapid development and the central break, e2-e4.
3...Nf6 4. Bg5 Be7 5. Bxf6
White exchanges in order to break with e2-e4. The inherent problem with the Dutch Defense is the early weakening of the kingside with 1...f5.
5...Bxf6 6. e4
White is missing his dark-squared Bishop. Recommended for Black is 6...d5, which forces White to clarify his intentions in the center.
6...fxe4
Not best, as it activates White's QN.

即每一行包含连续的带编号着法(白方着法带回合号,黑方着法紧跟),对应注释单独一行输出。


修改后的完整代码

import chess.pgn
import io
import os


def handle_san_error(pgn_file, game_str, san_error):
    # 跳过有问题的着法
    lines = game_str.splitlines()
    problematic_move = str(san_error).split()[2].strip("'")
    new_lines = [line for line in lines if problematic_move not in line]

    print(f"文件出错: {pgn_file}")
    print("问题着法:", problematic_move)

    return "\n".join(new_lines)

def process_pgn_files(pgn_files, output_file):
    with open(output_file, 'w', encoding='utf-8') as out_file:
        first_game = True
        for pgn_file in pgn_files:
            print(f"正在处理文件: {pgn_file}")
            with open(pgn_file, encoding='utf-8') as file:
                game_str = file.read()
                game_io = io.StringIO(game_str)

                while True:
                    try:
                        game_io.seek(0)
                        game = chess.pgn.read_game(game_io)
                        if game is None:
                            break
                    except chess.IllegalMoveError as e:
                        game_str = handle_san_error(pgn_file, game_str, e)
                        game_io = io.StringIO(game_str)
                        continue

                    if not first_game:
                        out_file.write('===\n\n')
                    first_game = False

                    node = game
                    current_turn_line = []
                    current_comment = ""
                    turn_number = 1

                    while not node.is_end():
                        move = node.move
                        if move is None:
                            break

                        # 获取标准代数记谱法(SAN)的着法
                        san_move = node.board().san(move)
                        # 判断当前是白方还是黑方着法
                        if node.board().turn == chess.WHITE:
                            # 白方着法,先写入之前积累的内容(如果有)
                            if current_turn_line:
                                out_file.write(' '.join(current_turn_line) + '\n')
                                if current_comment:
                                    out_file.write(current_comment.strip() + '\n\n')
                                    current_comment = ""
                            # 新回合,添加回合号+着法
                            current_turn_line = [f"{turn_number}.{san_move}"]
                            turn_number += 1
                        else:
                            # 黑方着法,直接追加到当前行
                            current_turn_line.append(san_move)

                        # 收集当前节点的注释
                        if node.comment:
                            current_comment += node.comment.strip() + ' '

                        node = node.next()

                    # 处理最后一组着法和注释
                    if current_turn_line:
                        out_file.write(' '.join(current_turn_line) + '\n')
                        if current_comment:
                            out_file.write(current_comment.strip() + '\n\n')

pgn_directory = 'directory'
output_file = 'output.txt'

pgn_files = [os.path.join(pgn_directory, f) for f in os.listdir(pgn_directory) if f.endswith('.pgn')]

process_pgn_files(pgn_files, output_file)

关键修改说明

  1. 着法格式转换:用node.board().san(move)替代str(move),输出国际象棋通用的标准代数记谱法(SAN)。
  2. 回合分组逻辑:跟踪回合数,将同一回合的白、黑方着法合并到同一行,白方着法前自动添加回合编号。
  3. 注释关联输出:收集同一组着法对应的所有注释,在着法行之后单独输出,保证注释与对应着法的关联性。
  4. 多游戏分隔:在不同游戏之间添加===分隔符,清晰区分多个游戏的内容。
  5. 编码兼容:打开文件时指定encoding='utf-8',避免中文或特殊字符注释出现乱码。

内容的提问来源于stack exchange,提问作者Dominic Matthews

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:44:59