123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #!/usr/bin/env python3
- import json
- import os
- import re
- import shutil
- import sys
- import threading
- import time
- import bs4
- import requests
- seriesRequestComplete = False
- majorSeries = set()
- majorMatches = {}
- minorMatches = set()
- backupFileName = os.path.join(os.path.dirname(sys.argv[0]), "scores.json")
- fileName = os.path.join(os.path.dirname(sys.argv[0]), "../noball/scores.json")
- matchData = {}
- rssContent = None
- def check():
- global seriesRequestComplete
- try:
- websiteContent = requests.get("http://www.espncricinfo.com/?edition-view=espncricinfo-en-ww").text
- finally:
- seriesRequestComplete = True
-
- soup = bs4.BeautifulSoup(websiteContent, 'html.parser')
- majorSeries_list = []
- for link in soup.find_all("a", attrs={
- "class": "quicklinks_list__link",
- "name": lambda name: name.startswith('&lpos=cricket:keyseries:') and not name.endswith(':app')
- }):
- try:
- majorSeries_list.append(re.match('/series/_/id/([0-9]+)/', link['href']).groups()[0])
- except AttributeError:
- pass
- majorSeries_list = majorSeries_list[:-3 + len(majorSeries_list) // 2]
- global majorSeries
- majorSeries = set(majorSeries_list)
- global majorMatches
- global minorMatches
- for match, series in majorMatches.items():
- if series not in majorSeries:
- minorMatches.add(match)
- majorMatches.pop(match)
- rssContent_local = bs4.BeautifulSoup(requests.get("http://static.espncricinfo.com/rss/livescores.xml").text, 'html.parser')
- matchUrlList = set()
- for match in rssContent_local.find_all('item'):
- url = match.guid.get_text().strip()
- matchUrlList.add(url)
- match.link['href'] = url
- global rssContent
- rssContent = rssContent_local
- curMatches = set(majorMatches.keys()).union(minorMatches)
-
- for match in matchUrlList - curMatches:
- try:
- seriesId, matchId = getIds(match)
- except:
- minorMatches.add(match)
- continue
-
- if seriesId in majorSeries:
- majorMatches[match] = seriesId
- index = max(list(matchData.keys()) + [ -1 ]) + 1
- matchData[index] = { 'url': match, 'status': rssContent.find('link', href=match).parent.title.get_text() }
- threading.Thread(target=startUpdater, args=(match, matchId, seriesId, index)).start()
- else:
- minorMatches.add(match)
-
- for match in curMatches - matchUrlList:
- try:
- majorMatches.pop(match)
- except KeyError:
- minorMatches.remove(match)
-
- with open(backupFileName, 'w') as _file:
- json.dump(list(matchData.values()), _file)
- shutil.copy2(backupFileName, fileName)
- os.remove(backupFileName)
- def getIds(match):
- return re.search("/series/([0-9]+)/[^/]+/([0-9]+)", requests.get(match).url).groups()
- def startUpdater(matchUrl, matchId, seriesId, key):
- page = 1
- while True:
- try:
- matchSummary = rssContent.find('link', href=matchUrl).parent.title.get_text()
-
- if re.search(" [*]( |$)", matchSummary) and not re.search(" [&] ( |$)", matchSummary):
- apiLink = "http://site.api.espn.com/apis/site/v2/sports/cricket/{}/playbyplay".format(seriesId)
-
- innings = 1
- ballByBallData = [ [] ]
-
- cgiParams = { "contentorigin": "espn",
- "lang": "en",
- "event": matchId,
- "page": page
- }
- commentaryData = requests.get(apiLink, cgiParams).json()['commentary']
- pageCount = commentaryData['pageCount']
- if pageCount > 1:
- page = pageCount
- cgiParams['page'] = page
- commentaryData = requests.get(apiLink, cgiParams).json()['commentary']
-
- lastBall = next(ball for ball in reversed(commentaryData['items']) if 'overs' in ball['over'])
-
- innings = lastBall['innings']
- runs = innings['runs']
- wickets = innings['wickets']
- target = innings['target']
- over = lastBall['over']
- limit = over['limit']
- batsman = lastBall['batsman']
- otherBatsman = lastBall['otherBatsman']
- bowler = lastBall['bowler']
-
- score = "{}{} ({}{} ov{}) ({}{} {}*, {} {}/{})".format(runs, "/{}".format(wickets) if wickets < 10 else "", over['overs'], "/{:.0f}".format(limit) if limit > 0 else "", ", target {}".format(target) if target > 0 else "", "{} {}*, ".format(batsman['athlete']['displayName'], batsman['totalRuns']) if not lastBall['dismissal']['dismissal'] else "", otherBatsman['athlete']['displayName'], otherBatsman['totalRuns'], bowler['athlete']['displayName'], bowler['wickets'], bowler['conceded'])
- ballsRemaining = innings['remainingBalls']
- battingTeam = lastBall['team']['displayName']
- bowlingTeam = bowler['team']['displayName']
- result = None
- if target > 0:
- remaining = " (with {} remaining)".format("{} ov".format(innings['remainingOvers']) if ballsRemaining > 90 else "{} balls".format(ballsRemaining)) if limit > 0 else ""
- if runs >= target:
- result = "{} won by {} wickets{}".format(battingTeam, 10 - wickets, remaining)
- elif ballsRemaining == 0 or wickets == 10:
- if runs == target - 1:
- result = "Match tied"
- else:
- result = "{} won by {} runs".format(bowlingTeam, target - runs - 1)
- else:
- result = "{} need {} runs to win{}".format(battingTeam, target - runs, remaining)
- matchSummary = re.sub("[^ ]+ +[*]", score.replace('\\', '\\\\'), matchSummary)
- if result:
- matchSummary += " - " + result
-
- matchData[key]['status'] = matchSummary
- except Exception as e:
- print("{} - {}: {}".format(time.time(), type(e), e))
- finally:
- time.sleep(10)
- if matchUrl not in majorMatches:
- matchData.pop(key)
- break
- while True:
- checkThread = threading.Thread(target=check, args=[])
- checkThread.start()
- while not seriesRequestComplete:
- time.sleep(.01)
- seriesRequestComplete = False
- nextThreadStart = time.time() + 20
- checkThread.join()
- time.sleep(max(0, nextThreadStart - time.time()))
|