You will need to install a few libraries from the command prompt.
- Code: Select all
pip3 install selenium
pip3 install beautifulsoup4
pip3 install lxml
pip3 install tabulate
pip3 install pywin32
You will need to have Google Chrome browser installed and also chromedriver.exe needs to be copied to the same folder as your .py file.
get it here
Python code here:-
- Code: Select all
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from datetime import date
from datetime import datetime
from dataclasses import dataclass,field
from typing import Dict
from tabulate import tabulate
import time
import win32com.client
def isTodaysMarket(venue):
todayStr = date.today().strftime("%d{dMod} %b")
d = date.today().day
if d == 1 or d == 21 or d == 31 : dMod = "st"
elif d == 2 or d == 22: dMod = "nd"
elif d == 3 or d == 23: dMod = "rd"
else: dMod = "th"
todayStr = todayStr.replace("{dMod}",dMod)
return venue.find(todayStr) != -1
@dataclass
class BAPrice:
backOdds:float
layOdds:float
@dataclass
class BAMarket:
venue: str
winMarketId: str
placeMarketId: str
winPrices: Dict[str, BAPrice] = field(default_factory=dict)
placePrices: Dict[str, BAPrice] = field(default_factory=dict)
def checkBA(BA):
baMarkets = {}
excludeMarkets = ["Each Way","TBP","Match Betting","To Win By Over","Without"]
sports = BA.getSports
for sport in sports:
if sport.sport == "Horse Racing":
countries = BA.getEvents(sport.sportId)
for country in countries:
if country.eventName == "GB" or country.eventName == "IRE":
countryCode = country.eventName
if countryCode == "GB": countryCode = "UK"
venues = BA.getEvents(country.eventId)
for venue in venues:
if isTodaysMarket(venue.eventName):
markets = BA.getEvents(venue.EventId)
placeMarketId = 0
winMarketId = 0
for market in markets:
if not any(ele in market.eventName for ele in excludeMarkets):
if market.eventName == "To Be Placed":
placeMarketId = market.eventId
else:
winMarketId = market.eventId
if winMarketId !=0 and placeMarketId !=0:
baMarket = BAMarket(venue.eventName, winMarketId, placeMarketId)
winMarketId = 0
placeMarketId = 0
startTime = market.startTime.strftime("%d%m%y_%H:%M")
#print(f"{baMarket.venue} {startTime} {baMarket.winMarketId} {baMarket.placeMarketId}")
baMarkets[f"{countryCode}_{startTime}"] = baMarket
return baMarkets
def getBAPrices(BA, baMarket):
# get win prices
while True:
baPrices = BA.getPrices
marketId = ''
for bfOdds in baPrices:
bfPrice = BAPrice(float(bfOdds.backOdds1), float(bfOdds.layOdds1))
baMarket.winPrices[bfOdds.Selection] = bfPrice
marketId = bfOdds.marketId
if int(marketId) == baMarket.winMarketId:
break
else:
baMarket.winPrices.clear()
time.sleep(1)
# get place prices
BA.openMarket(baMarket.placeMarketId, 1)
while True:
baPrices = BA.getPrices
marketId = ''
for bfOdds in baPrices:
bfPrice = BAPrice(float(bfOdds.backOdds1), float(bfOdds.layOdds1))
baMarket.placePrices[bfOdds.Selection] = bfPrice
marketId = bfOdds.marketId
if int(marketId) == baMarket.placeMarketId:
break
else:
baMarket.placePrices.clear()
time.sleep(1)
def getBookieNames(soup):
bookieNames = {}
bookies = soup.find_all('a', class_ = 'bk-logo-main-90 bk-logo-click')
for bookie in bookies:
bookieNames[bookie['data-bk']] = bookie['title']
return bookieNames
def checkRacingPost(BA,baMarkets):
options = Options()
options.headless = True
options.add_argument("--window-size=1920x1080")
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
url = 'https://www.oddschecker.com'
browser = webdriver.Chrome(options=options)
browser.get(url)
soup = BeautifulSoup(browser.page_source, 'lxml')
browser.quit()
venues = soup.find_all('div', class_ = 'race-details')
for venue in venues:
venueDetails = venue.find('div', class_ = 'venue-details')
country = venueDetails.span.text
venueName = venueDetails.a.text
if country == 'UK' or country == 'IRE':
races = venue.find_all('div', class_ = 'racing-time')
for race in races:
raceURL = race.a['href']
if race.a.has_attr('data-time'):
raceTime = race.a['data-time']
date1 = datetime.now()
date2 = datetime.strptime(raceTime,"%Y-%m-%d %H:%M:%S")
diff = date2 - date1
if diff.total_seconds() >=300:
raceTimeStr = date2.strftime("%d%m%y_%H:%M")
baMarketsKey = f"{country}_{raceTimeStr}"
if baMarketsKey in baMarkets.keys():
baMarket = baMarkets[baMarketsKey]
BA.openMarket(baMarket.winMarketId, 1)
#print(f"Checking {country} {venueName} {raceURL}")
browser = webdriver.Chrome(options=options)
browser.get(f"https://www.oddschecker.com{raceURL}")
soup1 = BeautifulSoup(browser.page_source, 'lxml')
browser.quit()
bookieNames = getBookieNames(soup1)
# create list of Betfair prices
getBAPrices(BA, baMarket)
horses = soup1.find_all('tr', class_ = 'diff-row evTabRow bc')
# get list of Oddschecer prices
for horse in horses:
horseName=horse['data-bname']
bookies = horse.find_all('td')
for bookie in bookies:
if bookie.has_attr('data-bk'):
bookieName = bookieNames[bookie['data-bk']]
odds = float(bookie['data-odig'])
ewDenom = '0'
placeOdds = 0.00
if bookie.has_attr('data-ew-denom'): ewDenom = bookie['data-ew-denom']
if ewDenom != '0':
placeOdds = float(((float(odds) - 1) / int(ewDenom)) + 1)
if horseName in baMarket.winPrices.keys() and horseName in baMarket.placePrices.keys():
bfWinPrice = baMarket.winPrices[horseName]
bfPlacePrice = baMarket.placePrices[horseName]
if bfPlacePrice.layOdds < placeOdds and bfWinPrice.layOdds <= float(odds) and bfPlacePrice.layOdds > 0 and bfWinPrice.layOdds > 0 and int(ewDenom) > 1:
ifWinBookie = (stake*(odds-1)) + (stake*(placeOdds-1))
ifPlaceBookie = (stake*(placeOdds-1)) - stake
ifLoseBookie = -(stake * 2)
ifWinBf = -((stake*(bfWinPrice.layOdds-1)) + (stake*(bfPlacePrice.layOdds-1)))
ifPlaceBf = -((stake*(bfPlacePrice.layOdds-1))) + stake
ifLoseBf = stake * 2
print(tabulate([[f"{raceTime} {venueName}",horseName]],tablefmt="fancy_grid"))
print(tabulate([[bookieName,odds,placeOdds,ifWinBookie,ifPlaceBookie,ifLoseBookie],
['Betfair',bfWinPrice.layOdds,bfPlacePrice.layOdds,ifWinBf,ifPlaceBf,ifLoseBf],
['Profit','','',ifWinBookie+ifWinBf,ifPlaceBookie+ifPlaceBf,ifLoseBookie+ifLoseBf]],
headers=['Bookmaker','Win Odds','Place Odds','If Win','If Place','If Lose'],
tablefmt="fancy_grid",floatfmt=".2f"),end="\n\n")
#print(f"{horseName} Bookie:{bookieName} EW denom:{ewDenom} Win odds:{odds} Place Odds:{placeOdds} Betfair Win Odds:{bfWinPrice.layOdds} Betfair Place Odds:{bfPlacePrice.layOdds}")
stake = 50.00
BA = win32com.client.Dispatch('BettingAssistantCom.Application.ComClass')
baMarkets = checkBA(BA)
checkRacingPost(BA,baMarkets)