-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscoresparser.go
156 lines (127 loc) · 3.69 KB
/
scoresparser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package scoresparser
import (
"fmt"
"io"
"log"
"strconv"
"strings"
"golang.org/x/net/html"
)
// Fixture game result
type Fixture struct {
Competition string
HomeTeam string
AwayTeam string
HomeTeamScore int
AwayTeamScore int
Aside string
}
// CompetitionNames interesting competitions
var CompetitionNames = map[string]bool{
"Premier League": true,
"Championship": true,
"League One": true,
"League Two": true,
"National League": true,
}
func panicClass(node *html.Node, className string) *html.Node {
foundClassAttr := false
for _, a := range node.Attr {
if a.Key == "class" && strings.Contains(a.Val, className) {
foundClassAttr = true
break
}
}
if !foundClassAttr {
panic("node does not have class: " + className)
}
return node
}
func panicTag(node *html.Node, tag string) *html.Node {
if node.Type != html.ElementNode || node.Data != tag {
panic("node [" + node.Data + "] is not an element of tag " + tag)
}
return node
}
func parseTeamScore(node *html.Node) (string, int) {
teamName := panicTag(
panicClass(node.FirstChild, "sp-c-fixture__team-name").FirstChild.FirstChild,
"abbr").FirstChild.Data
score, err := strconv.Atoi(panicClass(
panicClass(node.FirstChild.NextSibling, "sp-c-fixture__block").FirstChild,
"sp-c-fixture__number").FirstChild.Data)
if err != nil {
panic("error parsing score for [" + teamName + "] " + err.Error())
}
return teamName, score
}
func parseFixture(competition string, fixtureNode *html.Node, asideNode *html.Node) Fixture {
var fixture Fixture
fixture.Competition = competition
comment := asideNode.FirstChild.FirstChild.NextSibling.FirstChild.NextSibling
if comment.Type != html.ElementNode || comment.Data != "abbr" {
panic("not an aside abbr")
}
fixture.Aside = comment.FirstChild.Data
home := panicClass(fixtureNode.FirstChild, "sp-c-fixture__team--home")
away := panicClass(fixtureNode.LastChild, "sp-c-fixture__team--away")
fixture.HomeTeam, fixture.HomeTeamScore = parseTeamScore(home)
fixture.AwayTeam, fixture.AwayTeamScore = parseTeamScore(away)
fmt.Println(fixture)
return fixture
}
func parseGame(competition string, n *html.Node) Fixture {
if n.Type != html.ElementNode || n.Data != "li" {
panic("not an list of matches")
}
article := n.FirstChild.FirstChild
if article.Type != html.ElementNode || article.Data != "article" {
panic("not an article")
}
fixture := article.FirstChild
aside := fixture.NextSibling
return parseFixture(competition, fixture, aside)
}
func parseComp(compName string, n *html.Node) []Fixture {
var games []Fixture
if n.Type != html.ElementNode || n.Data != "ul" {
panic("not an list of matches")
}
for item := n.FirstChild; item != nil; item = item.NextSibling {
games = append(games, parseGame(compName, item))
}
return games
}
func parseResults(n *html.Node, fixtureMap map[string][]Fixture) {
nextNode := n.FirstChild
foundLeague := false
if n.Type == html.ElementNode && n.Data == "h3" {
for _, a := range n.Attr {
if a.Key == "class" && strings.Contains(a.Val, "sp-c-match-list-heading") {
competition := n.FirstChild.Data
_, present := CompetitionNames[competition]
if present {
fixtures := parseComp(competition, n.NextSibling)
fixtureMap[competition] = fixtures
}
foundLeague = true
}
}
}
if foundLeague {
return
}
for c := nextNode; c != nil; c = c.NextSibling {
parseResults(c, fixtureMap)
}
}
// ParseBBCScores parse matches from the BBC sports website
func ParseBBCScores(htmlPage io.Reader) map[string][]Fixture {
node, err := html.Parse(htmlPage)
if err != nil {
log.Fatal(err)
}
compFixtures := make(map[string][]Fixture)
parseResults(node, compFixtures)
return compFixtures
}