DaveM@23: import random DaveM@23: import csv DaveM@23: import re DaveM@23: import requests DaveM@23: import time DaveM@23: from bs4 import BeautifulSoup DaveM@23: DaveM@23: import pdb DaveM@23: DaveM@23: class compatibility: DaveM@23: def __init__(self): DaveM@23: self.rules = [] DaveM@23: self.uniqueID = 0 DaveM@23: print 'Warning, need to fix [Vertex, Ascendant House, South Node, IC/MC and None Location] issues' DaveM@23: DaveM@23: def addRule(self,planetTuple,aspectList,score): DaveM@23: rule = compatibilityRule(self.uniqueID,planetTuple,aspectList,score) DaveM@23: self.rules.append(rule) DaveM@23: self.uniqueID += 1 DaveM@23: DaveM@23: def findRule(self,planet): DaveM@23: ruleList = [r for r in self.rules if r.planet == planet] DaveM@23: print ruleList DaveM@23: return ruleList DaveM@23: DaveM@23: def readFile(self,filename): DaveM@23: text = [] DaveM@23: with open(filename) as fp: DaveM@23: line = fp.readline() DaveM@23: text.append(line.strip()) DaveM@23: while line: DaveM@23: line = fp.readline() DaveM@23: text.append(line.strip()) DaveM@23: return text DaveM@23: DaveM@23: def parseCompatRules(self,filename): DaveM@23: comList = self.readFile(filename) DaveM@23: for com in comList: DaveM@23: # print com DaveM@23: planetTuple = None DaveM@23: aspectList = None DaveM@23: score = None DaveM@23: c = com.split(',') DaveM@23: if len(c) == 4: DaveM@23: if len(c[1]) > 1: DaveM@23: aspectList = [] DaveM@23: planetTuple = tuple((c[0].lower(),c[2].lower())) DaveM@23: score = int(c[3]) DaveM@23: for subset in c[1].lower().split(' '): DaveM@23: aspectList.append(subset) DaveM@23: elif len(c[1]) == 0 : DaveM@23: if 'house' not in c[2]: DaveM@23: print 'some error where rule is not house' DaveM@23: planetTuple = (c[0].lower(),'house') DaveM@23: houseNo = re.findall('\d+', c[2]) DaveM@23: if len(houseNo) != 1: DaveM@23: print 'multiple house numbers found - ERROR' DaveM@23: aspectList = int(houseNo[0]) DaveM@23: score = int(c[3]) DaveM@23: self.addRule(planetTuple,aspectList,score) DaveM@23: DaveM@23: def calcCompatibility(self, horiscope): DaveM@23: score = 0 DaveM@23: for r in sorted(self.rules): DaveM@23: if 'vertex' in r.planet: DaveM@23: # print 'ERROR - catch Vertex issue' DaveM@23: pass DaveM@23: elif 'southnode' in r.planet: DaveM@23: # print 'ERROR - catch South Node issue' DaveM@23: pass DaveM@23: elif 'ic/mc' in r.planet: DaveM@23: # print 'ERROR - catch IC/MC issue' DaveM@23: pass DaveM@23: elif r.planet[1] == 'house' and r.planet[0] == 'asc': DaveM@23: # print 'ERROR - catch Ascendant House issue' DaveM@23: pass DaveM@23: elif horiscope.planets[r.planet[0]].angleA is None: DaveM@23: # print 'Error - None Location' DaveM@23: return None DaveM@23: elif r.planet[1] == 'house': DaveM@23: if horiscope.isInHouse(r.planet[0],r.aspect): DaveM@23: score += r.score DaveM@23: print r.planet[0] +' '+ r.planet[1] +' '+ str(aspect)+' '+str(r.score) DaveM@23: elif r.planet[0] == r.planet[1]: DaveM@23: aspect,variance = horiscope.calcAspect(r.planet[0],r.planet[1]) DaveM@23: if aspect is not None: DaveM@23: if aspect in r.aspect: DaveM@23: score += r.score DaveM@23: print r.planet[0]+' '+aspect +' '+ r.planet[1] +' '+ str(r.score) DaveM@23: else: DaveM@23: for order in [0,1]: DaveM@23: aspect,variance = horiscope.calcAspect(r.planet[order],r.planet[not order]) DaveM@23: if aspect is not None: DaveM@23: # print aspect DaveM@23: # currentR = r DaveM@23: # pdb.set_trace() DaveM@23: if aspect in r.aspect: DaveM@23: score += r.score DaveM@23: print r.planet[0] +' '+ aspect +' '+ r.planet[1] +' '+ str(r.score) DaveM@23: else: DaveM@23: print r.planet[0] +' '+ aspect +' '+ r.planet[1] +' 0' DaveM@23: print score DaveM@23: return score DaveM@23: DaveM@23: DaveM@23: DaveM@23: DaveM@23: class compatibilityRule: DaveM@23: def __init__(self,uniqueId,planetTuple,aspectList,score): DaveM@23: self.id = uniqueId DaveM@23: self.planet = planetTuple DaveM@23: self.aspect = aspectList DaveM@23: self.score = score DaveM@23: DaveM@23: DaveM@23: class Person: DaveM@23: url = 'https://horoscopes.astro-seek.com/calculate-love-compatibility/' DaveM@23: def __init__(self,personDict): DaveM@23: # self. = planetPositions() DaveM@23: self.id = personDict['ID'] DaveM@23: self.dob = personDict['DOB'] DaveM@23: self.tob = personDict['TOB'] DaveM@23: self.cob = personDict['COB'] DaveM@23: self.p_dob = personDict['pDOB'] DaveM@23: self.p_tob = personDict['pTOB'] DaveM@23: self.p_cob = personDict['pCOB'] DaveM@23: self.horiscope = None DaveM@23: self.resp = None DaveM@23: self.issue = 'INCOMPLETE' DaveM@23: DaveM@23: def identifyIssues(self): DaveM@23: if self.id is None: DaveM@23: self.issue = 'id' DaveM@23: elif self.dob is None: DaveM@23: self.issue = 'dob' DaveM@23: elif self.tob is None: DaveM@23: self.issue = 'tob' DaveM@23: elif self.cob is None: DaveM@23: self.issue = 'cob' DaveM@23: elif self.p_dob is None: DaveM@23: self.issue = 'p_dob' DaveM@23: elif self.p_tob is None: DaveM@23: self.issue = 'p_tob' DaveM@23: elif self.p_cob is None: DaveM@23: self.issue = 'p_cob' DaveM@23: else: DaveM@23: self.issue = None DaveM@23: return self.issue DaveM@23: DaveM@23: def makePayload(self): DaveM@23: if type(self.cob) is str: DaveM@23: cob_0 = float(self.cob.split(',')[0][1:]) DaveM@23: cob_1 = float(self.cob.split(',')[1]) DaveM@23: self.cob = (cob_0,cob_1) DaveM@23: if type(self.p_cob) is str: DaveM@23: pcob_0 = float(self.p_cob.split(',')[0][1:]) DaveM@23: pcob_1 = float(self.p_cob.split(',')[1]) DaveM@23: self.p_cob = (pcob_0,pcob_1) DaveM@23: if type(self.dob) is str: DaveM@23: self.dob = self.dob[1:-1].split(',') DaveM@23: if type(self.p_dob) is str: DaveM@23: self.p_dob = self.p_dob[1:-1].split(',') DaveM@23: if type(self.tob) is str: DaveM@23: self.tob = self.tob[1:-1].split(',') DaveM@23: if type(self.p_tob) is str: DaveM@23: self.p_tob = self.p_tob[1:-1].split(',') DaveM@23: DaveM@23: self.payload = {'send_calculation':'1', #Req DaveM@23: 'muz_narozeni_den':self.dob[0], DaveM@23: 'muz_narozeni_mesic':self.dob[1], DaveM@23: 'muz_narozeni_rok':self.dob[2], DaveM@23: 'muz_narozeni_hodina':self.tob[0], DaveM@23: 'muz_narozeni_minuta':self.tob[1], DaveM@23: 'muz_narozeni_city':'', DaveM@23: 'muz_narozeni_mesto_hidden':'Manually+place%3A+%C2%B0%27N%2C+%C2%B0%27E',#auto DaveM@23: 'muz_narozeni_stat_hidden':'XX', DaveM@23: 'muz_narozeni_podstat_kratky_hidden':'', DaveM@23: 'muz_narozeni_podstat_hidden':'', DaveM@23: 'muz_narozeni_podstat2_kratky_hidden':'', DaveM@23: 'muz_narozeni_podstat3_kratky_hidden':'', DaveM@23: 'muz_narozeni_input_hidden':'', DaveM@23: 'muz_narozeni_sirka_stupne':str(abs(self.cob[0])).split('.')[0], DaveM@23: 'muz_narozeni_sirka_minuty':str(float('0.'+str(self.cob[0]).split('.')[1])*60).split('.')[0], DaveM@23: 'muz_narozeni_sirka_smer': '1' if self.cob[0]<0 else '0', #address N Dir (0':'N',1':'S) DaveM@23: 'muz_narozeni_delka_stupne':str(abs(self.cob[1])).split('.')[0], #address E - Main DaveM@23: 'muz_narozeni_delka_minuty':str(float('0.'+str(self.cob[1]).split('.')[1])*60).split('.')[0], DaveM@23: 'muz_narozeni_delka_smer': '1' if self.cob[1]<0 else '0', #address E Dir (0':'E',1':'W) DaveM@23: 'muz_narozeni_timezone_form':'auto', DaveM@23: 'muz_narozeni_timezone_dst_form':'auto', DaveM@23: 'send_calculation':'1', DaveM@23: 'zena_narozeni_den':self.p_dob[0], DaveM@23: 'zena_narozeni_mesic':self.p_dob[1], DaveM@23: 'zena_narozeni_rok':self.p_dob[2], DaveM@23: 'zena_narozeni_hodina':self.p_tob[0], DaveM@23: 'zena_narozeni_minuta':self.p_tob[1], DaveM@23: 'zena_narozeni_city':'', DaveM@23: 'zena_narozeni_mesto_hidden':'Manually+place%3A+%C2%B0%27N%2C+%C2%B0%27E', DaveM@23: 'zena_narozeni_stat_hidden':'XX', DaveM@23: 'zena_narozeni_podstat_kratky_hidden':'', DaveM@23: 'zena_narozeni_podstat_hidden':'', DaveM@23: 'zena_narozeni_podstat2_kratky_hidden':'', DaveM@23: 'zena_narozeni_podstat3_kratky_hidden':'', DaveM@23: 'zena_narozeni_input_hidden':'', DaveM@23: 'zena_narozeni_sirka_stupne':str(abs(self.p_cob[0])).split('.')[0], DaveM@23: 'zena_narozeni_sirka_minuty':str(float('0.'+str(self.p_cob[0]).split('.')[1])*60).split('.')[0], DaveM@23: 'zena_narozeni_sirka_smer': '1' if self.p_cob[0]<0 else '0', DaveM@23: 'zena_narozeni_delka_stupne':str(abs(self.p_cob[1])).split('.')[0], DaveM@23: 'zena_narozeni_delka_minuty':str(float('0.'+str(self.p_cob[1]).split('.')[1])*60).split('.')[0], DaveM@23: 'zena_narozeni_delka_smer': '1' if self.p_cob[1]<0 else '0', DaveM@23: 'zena_narozeni_timezone_form':'auto', DaveM@23: 'zena_narozeni_timezone_dst_form':'auto', DaveM@23: 'switch_interpretations':'0', DaveM@23: 'house_system':'placidus', DaveM@23: 'uhel_orbis':'#tabs_redraw'} DaveM@23: DaveM@23: def requestURL(self): DaveM@23: self.resp = requests.get(self.url, params=self.payload) DaveM@23: time.sleep(5) DaveM@23: return self.resp DaveM@23: DaveM@23: def parsePage(self): DaveM@23: self.horiscope = None DaveM@23: if('Please use valid date.' in self.resp.content): DaveM@23: self.issue = 'dob' DaveM@23: return self.horiscope DaveM@23: elif('Please use valid time.' in self.resp.content): DaveM@23: self.issue = 'tob' DaveM@23: return self.horiscope DaveM@23: gotLocation = 0 DaveM@23: self.horiscope = planetPositions() DaveM@23: soup = BeautifulSoup(self.resp.content, 'lxml') DaveM@23: tcCell = soup.find_all('div', attrs={'class':'right-sedy-banner-svetlejsi'}) DaveM@23: for cell in tcCell: DaveM@23: if "Planets in partner's house" in cell.get_text(): DaveM@23: gotLocation = 1 DaveM@23: divList = cell.find_all('div') DaveM@23: for i in range(len(divList)): DaveM@23: planetName = divList[i].getText().lower().strip().replace(':','').split(' ')[0] DaveM@23: if planetName in planetPositions.planetNames: DaveM@23: if gotLocation and not '/' in planetName: DaveM@23: self.horiscope.planets[planetName].setHouse(divList[i+2].getText(),divList[i+4].getText()) DaveM@23: else: DaveM@23: self.horiscope.planets[planetName].setLocation(divList[i+2].getText(),divList[i+1].img.attrs['alt'],0) DaveM@23: self.horiscope.planets[planetName].setLocation(divList[i+4].getText(),divList[i+3].img.attrs['alt'],1) DaveM@23: return self.horiscope DaveM@23: DaveM@23: DaveM@23: DaveM@23: class planetRelation: DaveM@23: noHouseList = ['asc','ic','dsc','mc','asc/mc','sun/moon'] DaveM@23: zodiacAngle = {'aries':0,'taurus':30,'gemini':60,'cancer':90,'leo':120,'virgo':150,'libra':180,'scorpio':210,'sagittarius':240,'capricorn':270,'aquarius':300,'pisces':330} DaveM@23: DaveM@23: def __init__(self,planetName): DaveM@23: self.name = planetName DaveM@23: self.angleA = None DaveM@23: self.angleB = None DaveM@23: if planetName not in planetRelation.noHouseList: DaveM@23: self.houseA = None DaveM@23: self.houseB = None DaveM@23: DaveM@23: def setLocation(self,value,sign,isB): DaveM@23: signVal = planetRelation.zodiacAngle[sign.lower()] DaveM@23: signVal+= float('.'.join(value.encode('ascii','replace').split('?'))[:-1]) DaveM@23: # print self.name,sign.lower(),planetRelation.zodiacAngle[sign.lower()],value,signVal DaveM@23: if not isB: DaveM@23: self.angleA = signVal DaveM@23: else: DaveM@23: self.angleB = signVal DaveM@23: DaveM@23: def setHouse(self,A,B): DaveM@23: self.houseA = int(A.encode('ascii','ignore')) DaveM@23: self.houseB = int(B.encode('ascii','ignore')) DaveM@23: DaveM@23: def test_random(self): DaveM@23: self.angleA = random.random()*360 DaveM@23: self.angleB = random.random()*360 DaveM@23: DaveM@23: DaveM@23: class planetPositions: DaveM@23: aspectDict = {'conjunction':0,'semi-square':45,'sextile':60,'square':90,'trine':120,'opposition':180} DaveM@24: aspectRange = {'conjunction':10,'semi-square':2,'sextile':4,'square':10,'trine':10,'opposition':10} DaveM@23: # zodiacAngle = {'aries':0,'taurus':30,'gemini':60,'cancer':90,'leo':120,'virgo':150,'libra':180,'scorpio':210,'sagittarius':240,'capricorn':270,'aquarius':300,'pisces':330} DaveM@23: # Taken from https://en.wikipedia.org/wiki/Astrological_sign, with reference from https://en.wikipedia.org/wiki/Astrological_symbols#Signs_of_the_zodiac DaveM@23: planetNames = ['sun','moon','mercury','venus','mars','jupiter','saturn','uranus','neptune','pluto','node','lilith','chiron','asc','ic','dsc','mc','asc/mc','sun/moon'] DaveM@23: def __init__(self): DaveM@23: self.planets = {} DaveM@23: for p in planetPositions.planetNames: DaveM@23: self.planets[p] = planetRelation(p) DaveM@23: self.aspect = {} DaveM@23: DaveM@23: def test_random(self): DaveM@23: for planet in self.planets: DaveM@23: self.planets[planet].test_random() DaveM@23: DaveM@23: def calcAngle(self,componentA,componentB): DaveM@23: self.angle = abs(self.planets[componentA].angleA - self.planets[componentB].angleB) DaveM@23: DaveM@23: def calcAspect(self,componentA,componentB): DaveM@23: self.calcAngle(componentA,componentB) DaveM@23: for aspect in planetPositions.aspectDict: DaveM@24: if self.angle-self.aspectRange[aspect] < self.aspectDict[aspect] and self.angle+self.aspectRange[aspect] > self.aspectDict[aspect]: DaveM@23: aspectDiff = round(abs(self.angle - planetPositions.aspectDict[aspect]),2) DaveM@23: self.aspect[componentA,componentB] = (aspect,aspectDiff) DaveM@24: print componentA,self.planets[componentA].angleA,componentB,self.planets[componentB].angleB,self.angle,aspect,aspectDiff DaveM@23: return aspect,aspectDiff DaveM@23: return None,None DaveM@23: DaveM@23: def isInHouse(self,component,houseNo): DaveM@23: # print (self.planets[component].houseA,self.planets[component].houseB,houseNo) DaveM@23: if (self.planets[component].houseA == houseNo) or (self.planets[component].houseB == houseNo): DaveM@23: return True DaveM@23: return False DaveM@23: DaveM@23: def makeAllAspectTreple(self): DaveM@23: self.aspectTreple = {} DaveM@23: for p1 in planetPositions.planetNames: DaveM@23: for p2 in planetPositions.planetNames: DaveM@23: aspect = self.calcAspect(p1,p2)[0] DaveM@23: if aspect is not None: DaveM@23: self.aspectTreple[(p1,p2,aspect)] = 1 DaveM@23: DaveM@23: def calcAllAspects(self): DaveM@23: for p1 in planetPositions.planetNames: DaveM@23: for p2 in planetPositions.planetNames: DaveM@23: self.calcAspect(p1,p2) DaveM@23: DaveM@23: def printPositions(self): DaveM@23: for p in planetPositions.planetNames: DaveM@23: if p in planetRelation.noHouseList: DaveM@23: print p,self.planets[p].angleA,self.planets[p].angleB DaveM@23: else: DaveM@23: print p,self.planets[p].angleA,self.planets[p].angleB,self.planets[p].houseA,self.planets[p].houseB DaveM@23: DaveM@23: DaveM@23: DaveM@23: DaveM@23: