Search code examples
pythonhtmlexport-to-csvchesspython-chess

Exporting Chess moves and images into HTML or CSV format


I have used the post (Printing individual moves with the python-chess library) to obtain the individual moves and display image of the chess board. See the code below.

import chess
from io import StringIO
import chess.pgn

#create a virtual board
board = chess.Board()    
#Paste PGN data    
pgn_string = """
1 e4 e6 2 d4 c6 3 Nf3 Nf6 4 Bg5 h6 5 Bf4 Na6 6 Bc4 d5 7 Bd3 Nxe4 8 O-O Nb4 9 Ne5 a5 
10 Qg4 f5 11 Qg6+ Ke7 12 Qf7+ Kd6 13 Nc4# 
"""

# Converting the string into StringIO object
pgn = StringIO(pgn_string)
# Reading the game
game = chess.pgn.read_game(pgn) 
#Printing and displaying the moves in algebraic notation
for move in game.mainline_moves():
        print(board.san(move))
        board.push(move)
        display(board)

I am able to obtain the output (see the image below) in jupyter for each moves and their corresponding board image (inside a scrolled window in jupyter) enter image description here

I am trying to figure out if the above data (i.e individual move and their image) can be exported to HTML or CSV format, so that i can analyse the moves, as it is difficult to analyze in jupyter. Thanks in advance


Solution

  • Command board.san(move) gives current move as text and you can keep it on list to save it later.

    In documentation I found function chess.svg.board() which generates string with SVG image - and you can save in file using standard open(), write(), close()

    Every browser can display image svg in HTML

    You need only loop to create HTML with all moves and images

    import chess
    import chess.pgn
    from io import StringIO
    
    board = chess.Board()    
    
    pgn_string = """
    1 e4 e6 2 d4 c6 3 Nf3 Nf6 4 Bg5 h6 5 Bf4 Na6 6 Bc4 d5 7 Bd3 Nxe4 8 O-O Nb4 9 Ne5 a5 
    10 Qg4 f5 11 Qg6+ Ke7 12 Qf7+ Kd6 13 Nc4# 
    """
    
    pgn = StringIO(pgn_string)
    
    game = chess.pgn.read_game(pgn) 
    
    steps = []
    for number, move in enumerate(game.mainline_moves()):
        text = board.san(move) 
        print(text)
        
        # keep current step on list
        steps.append(text)
    
        board.push(move)
        #display(board)
    
        # create string with SVG image
        svg = chess.svg.board(board)
        
        # save string in file with name `board-0.svg`, `board-1.svg`, etc.
        with open(f'board-{number}.svg', 'w') as fh:
            fh.write(svg)
        
    # --- after loop ---
    
    #print(steps)
    
    # create string with HTML
    
    html = ""
    
    for number, move in enumerate(steps):
        # add move
        html += f'{move}</br>\n'
        
        # add image `board-0.svg`, `board-1.svg`, etc. (with width=300 to make it smaller)
        html += f'<img src="board-{number}.svg" width="300"></br>\n'
        
    # save html in file    
    with open('index.html', 'w') as fh:
        fh.write(html)
    

    Screenshot from web browser:

    enter image description here


    BTW:

    It needs files board-0.svg, board-1.svg, etc. to display it but you may also put string directly in HTML.

    import chess
    import chess.pgn
    from io import StringIO
    
    board = chess.Board()    
    
    pgn_string = """
    1 e4 e6 2 d4 c6 3 Nf3 Nf6 4 Bg5 h6 5 Bf4 Na6 6 Bc4 d5 7 Bd3 Nxe4 8 O-O Nb4 9 Ne5 a5 
    10 Qg4 f5 11 Qg6+ Ke7 12 Qf7+ Kd6 13 Nc4# 
    """
    
    pgn = StringIO(pgn_string)
    
    game = chess.pgn.read_game(pgn) 
    
    steps = []
    for number, move in enumerate(game.mainline_moves()):
        text = board.san(move) 
        print(text)
        
        board.push(move)
        #display(board)
    
        # create string with SVG image (with size=300 to make it smaller)
        svg = chess.svg.board(board, size=300)
    
        # keep current step [text, svg] on list
        steps.append( [text, svg])
    
    # --- after loop ---
    
    #print(steps)
    
    # create string with HTML
    
    html = ""
    
    for number, (text, svg) in enumerate(steps):
        # add move
        html += f'{text}</br>\n'
    
        # add image
        html += f'{svg}</br>\n'
        
    # save html in file    
    with open('index.html', 'w') as fh:
        fh.write(html)