Opening puzzles
On Lichess it's possible to train opening related puzzles:
https://lichess.org/training/opening
Puzzles for other phases of the game are available as well:
https://lichess.org/training/themes
Keep in mind, that the puzzle selection will be only as good as the votes given by Lichess users. Also, as far as I know, it's not possible to select specific openings.
Statistics
Because of a question by @BCLC in the comments I found this link, where you can download all Lichess puzzles. I made a little table based on all puzzles tagged with "opening". Actual motifs are marked in bold other tags in italic.
Remember, that the statistics will be only as good as the data. Apparently there is one puzzle tagged with "opening" and "rookEndgame".
Tag |
Count |
Perc. |
short |
71723 |
74.27% |
advantage |
58328 |
60.40% |
crushing |
25978 |
26.90% |
fork |
20514 |
21.24% |
long |
11694 |
12.11% |
oneMove |
11204 |
11.60% |
mate |
9170 |
9.50% |
hangingPiece |
8307 |
8.60% |
discoveredAttack |
8110 |
8.40% |
kingsideAttack |
7507 |
7.77% |
pin |
6299 |
6.52% |
mateIn2 |
4618 |
4.78% |
trappedPiece |
4150 |
4.30% |
mateIn1 |
3597 |
3.72% |
attackingF2F7 |
3451 |
3.57% |
sacrifice |
3412 |
3.53% |
equality |
3099 |
3.21% |
intermezzo |
2842 |
2.94% |
defensiveMove |
2683 |
2.78% |
attraction |
2003 |
2.07% |
veryLong |
1954 |
2.02% |
deflection |
1952 |
2.02% |
capturingDefender |
1605 |
1.66% |
master |
1042 |
1.08% |
advancedPawn |
1022 |
1.06% |
clearance |
892 |
0.92% |
mateIn3 |
784 |
0.81% |
skewer |
741 |
0.77% |
exposedKing |
740 |
0.77% |
quietMove |
582 |
0.60% |
doubleCheck |
550 |
0.57% |
interference |
455 |
0.47% |
queensideAttack |
416 |
0.43% |
smotheredMate |
393 |
0.41% |
backRankMate |
212 |
0.22% |
enPassant |
177 |
0.18% |
mateIn4 |
120 |
0.12% |
castling |
110 |
0.11% |
masterVsMaster |
91 |
0.09% |
promotion |
89 |
0.09% |
bodenMate |
57 |
0.06% |
mateIn5 |
51 |
0.05% |
xRayAttack |
47 |
0.05% |
superGM |
35 |
0.04% |
doubleBishopMate |
28 |
0.03% |
dovetailMate |
20 |
0.02% |
underPromotion |
4 |
0.00% |
anastasiaMate |
3 |
0.00% |
hookMate |
1 |
0.00% |
arabianMate |
1 |
0.00% |
rookEndgame |
1 |
0.00% |
Code
Here is the Kotlin snippet I used to generate the table:
val data = File("lichess_db_puzzle.csv").readText().trim().split('\n')
.map { it.split(',')[7].split(' ') }.filter { it.contains("opening") }.flatten()
.groupingBy { it }.eachCount().toList().sortedByDescending { it.second }
for (i in 1..data.lastIndex) {
val t = if (data[i].first in listOf("advancedPawn", "anastasiaMate", "arabianMate", "attackingF2F7", "attraction", "backRankMate", "bodenMate", "capturingDefender", "clearance", "defensiveMove", "deflection", "discoveredAttack", "doubleBishopMate", "doubleCheck", "dovetailMate", "exposedKing", "fork", "hangingPiece", "hookMate", "interference", "intermezzo", "kingsideAttack", "mate", "mateIn1", "mateIn2", "mateIn3", "mateIn4", "mateIn5", "pin", "promotion", "queensideAttack", "quietMove", "sacrifice", "skewer", "smotheredMate", "trappedPiece", "underPromotion", "xRayAttack", "zugzwang")) "**" else "*"
println("| %-24s | %10s | %11s |".format("${t}${data[i].first}${t}", "${t}${data[i].second}${t}", "${t}${"%.2f".format(100.0 * data[i].second / data[0].second)}%${t}"))
}