def parse_df(df): e = { 'izena': 'Gipuzkoako traineru txapelketa', 'data': '2020-07-15 18:00', 'lekua': 'Orio' } estropada = Estropada(**e) for i, r in df.iterrows(): # tanda = int(tanda) if not isinstance(r['Postua'], type('str')): break tanda = 1 kalea = int(r['Kalea']) postua = int(r['Postua'][:-1]) denbora = r['Denbora'] taldea = r['TALDEA'] ziabogak = [r['1, Ziabo']] if '2, Ziabo' in df.columns: ziabogak.extend([r['2, Ziabo'], r['3, Ziabo']]) emaitza = { 'tanda': tanda, 'tanda_postua': postua, 'kalea': int(kalea), 'posizioa': postua, 'denbora': denbora, 'puntuazioa': postua, 'ziabogak': ziabogak } t = TaldeEmaitza(taldea, **emaitza) estropada.taldeak_add(t) return estropada
def parse(self, *args): '''Parse a result and return an estropada object''' urla = args[0] document = self.get_content(*args) (estropadaName, estropadaDate, lekua, liga) = self.parse_headings(document) opts = {'urla': urla, 'data': estropadaDate, 'liga': liga, 'lekua': lekua} self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document) self.parse_resume(document) return self.estropada
def parse_emaitzak_doc(filename): df = read_pdf(filename, pages=1, stream=True) neskak = df[0] nesken_emaitza = parse_data(neskak) e = { 'izena': 'Bizkaiako traineru txapelketa', 'data': '2020-07-15 18:00', 'lekua': 'Orio' } estropada = Estropada(**e) for e in nesken_emaitza: estropada.taldeak_add(e) print(estropada.get_json())
def parse(self, *args): '''Parse a result and return an estropada object''' document = self.get_content(*args) urla = args[0] estropadaDate = args[2] liga = args[3] d = datetime.datetime.strptime(estropadaDate, '%Y-%m-%d') (estropadaName) = self.parse_headings(document) opts = {'urla': urla, 'data': estropadaDate, 'liga': liga} self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document, d.year) if d.year <= 2008: self.calculate_tanda_posizioa() else: self.parse_resume(document) return self.estropada
def gtl_pdf_parser(docid, izena, data, lekua, import_to_db, filename, parse_to_csv): structure = [(1, 'JN'), (2, 'JG'), (3, 'SN'), (4, 'SG'), (5, 'SG')] e = None if import_to_db: import adaptors.couch as couchdb try: e = couchdb.getdoc(docid) del e['sailkapena'] except KeyError as err: e = { 'izena': izena, 'data': data, 'lekua': lekua } else: e = { 'izena': izena, 'data': data, 'lekua': lekua } estropada = Estropada(**e) kategoriak = [] if parse_to_csv: for kategoria in structure: logger.info(f'Reading page {kategoria[0]} for cat {kategoria[1]}') try: kategoria_emaitzak = parse_pdf_to_csv(filename, kategoria[0], kategoria[1], data) except Exception as e: print(f"Cannot parse {kategoria[0]} orrialdea") logger.error(e) else: for kategoria in structure: logger.info(f'Reading page {kategoria[0]} for cat {kategoria[1]}') try: kategoria_emaitzak = parse_data(kategoria[0], kategoria[1], data) kategoriak.append(kategoria[1]) for t in kategoria_emaitzak: estropada.taldeak_add(t) except Exception as e: print(f"Cannot parse {kategoria[0]} orrialdea") logger.error(e) estropada.kategoriak = kategoriak puntuazioak_kalkulatu(estropada) if import_to_db: estropada_json = estropada.get_json() estropada_obj = json.loads(estropada_json) if hasattr(estropada, '_rev'): estropada_obj['_rev'] = estropada._rev couchdb.setdoc(docid, estropada_obj) else: estropada.dump_json()
def estropadak_transform(row): if 'doc' in row: document = row['doc'] else: document = row row = normalize_id(row) izena = document.pop('izena') estropada = Estropada(izena, **document) return estropada
def test_estropada_with_common_props(): izena = 'Test estropada' props = {'lekua': 'Donostia', 'liga': 'ACT', 'data': '2020-06-01 17:00'} e = Estropada(izena, **props) assert type(e) == Estropada assert e.izena == izena assert e.lekua == props['lekua'] assert e.liga == props['liga'] assert e.data == props['data']
def test_estropada_with_sailkapena_with_dicts(): izena = 'Test estropada' props = { 'sailkapena': [{ 'talde_izena': 'Hondarribia', 'kalea': 1, 'tanda': 1 }, { 'talde_izena': 'Urdaibai', 'kalea': 2, 'tanda': 1 }] } e = Estropada(izena, **props) assert type(e) == Estropada assert e.izena == izena assert len(e.sailkapena) == 2 assert type(e.sailkapena[0]) == TaldeEmaitza assert e.sailkapena[0].talde_izena == 'Hondarribia' assert e.sailkapena[1].talde_izena == 'Urdaibai'
def test_estropada_with_sailkapena_with_team_emaitza_objects(): izena = 'Test estropada' props = { 'sailkapena': [ TaldeEmaitza('Hondarribia', **{ 'kalea': 1, 'tanda': 1 }), TaldeEmaitza('Urdaibai', **{ 'kalea': 2, 'tanda': 1 }) ] } e = Estropada(izena, **props) assert type(e) == Estropada assert e.izena == izena assert len(e.sailkapena) == 2 assert type(e.sailkapena[0]) == TaldeEmaitza assert e.sailkapena[0].talde_izena == 'Hondarribia' assert e.sailkapena[1].talde_izena == 'Urdaibai'
def parse(self, content): self.document = lxml.html.fromstring(content) table_rows = self.document.cssselect('.taula.tablepadding tr') estropadak = [] for i, row in enumerate(table_rows): if i == 0: continue anchor = row.cssselect('.race_name a') izena = anchor[0].text.strip() link = anchor[0].attrib['href'] lek_data = row.cssselect('.place') lekua = lek_data[0].text.strip() data = lek_data[1].text.strip() urla = self.base_url + link opts = { 'urla': urla, 'data': data, 'lekua': lekua, 'liga': self.liga, 'sailkapena': [] } estropada = Estropada(izena, **opts) estropadak.append(estropada) return estropadak
kategoria_base = None kategoriak_helper = [] for row in estropadakreader: eguna = row[3] if int(row[3]) < 10: eguna = f'0{row[3]}' data = f'2020-{month_index(row[1])}-{eguna}' print(row[5][0:2]) try: jardunaldia = int(row[5][0:2]) except ValueError: try: jardunaldia = int(row[5][0]) except ValueError: jardunaldia = None # print(f'{jardunaldia} [{data}] - {row[4]} - {row[5]}') datuak = { 'id': f'2020_GBL_{jardunaldia:02}', 'jardunaldia': jardunaldia, 'data': data, 'liga': 'GBL', 'lekua': row[4] } estropada = Estropada( f'Gipuzkoako batel liga, {jardunaldia}. Jardunaldia', **datuak) # print_pretty(estropada) print(estropada.get_json()) estropada_json = estropada.get_json() db[estropada.id] = json.loads(estropada_json)
id = None filename = sys.argv[1] izena = sys.argv[2] if sys.argv[3]: id = sys.argv[3] if sys.argv[4]: lekua = sys.argv[4] with open(filename, newline='') as csvfile: teamreader = csv.reader(csvfile, delimiter=",") e = {'izena': izena} if id: e = db[id] if lekua: e['lekua'] = lekua estropada = Estropada(**e) tanda = 0 kategoria_base = None kategoriak_helper = [] for row in teamreader: posizioa = None try: posizioa = int(row[1]) except ValueError as e: continue if posizioa == 1: kategoria_base = kategoriak[tanda] tanda = tanda + 1 kategoria = kategoria_base + ' ' + row[3] kategoriak_helper.append(kategoria)
filename = sys.argv[1] izena = sys.argv[2] # if sys.argv[3]: # id = sys.argv[3] with open(filename, newline='') as csvfile: teamreader = csv.reader(csvfile, delimiter=",") e = { 'izena': izena, 'data': '2020-09-13 10:00' } # if id: # e = db[id] if lekua: e['lekua'] = lekua estropada = Estropada(**e) kategoria_base = None kategoriak_helper = [] for row in teamreader: print(row) # if row[0].startswith('#'): # continue posizioa = None try: tanda = int(row[0]) tanda_posizioa = int(row[1]) posizioa = int(row[2]) kalea = int(row[5]) except ValueError as e: continue
class ArcParserLegacy(Parser): '''Base class to parse an ARC legacy(2006-2008) race result''' def __init__(self, **kwargs): pass def parse(self, *args): '''Parse a result and return an estropada object''' document = self.get_content(*args) urla = args[0] estropadaDate = args[2] liga = args[3] d = datetime.datetime.strptime(estropadaDate, '%Y-%m-%d') (estropadaName) = self.parse_headings(document) opts = {'urla': urla, 'data': estropadaDate, 'liga': liga} self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document, d.year) if d.year <= 2008: self.calculate_tanda_posizioa() else: self.parse_resume(document) return self.estropada def parse_headings(self, document): '''Parse headings table''' heading_one = document.cssselect('#contenido h1') estropada = heading_one[0].text.strip() estropada = estropada.replace("Resultados de: ", "") return (estropada) def parse_date(self, date): new_date = date.replace('Jun', '06') new_date = new_date.replace('Jul', '07') new_date = new_date.replace('Ago', '08') new_date = new_date.replace('Sept', '09') date_list = re.split('-', new_date) if len(date_list) == 3: new_date = date_list[2] + "-" + date_list[1] + "-" + date_list[0] return new_date def parse_tandas(self, document, urtea): tandas = document.cssselect('table.resultados') for num, text in enumerate(tandas): rows = text.findall('.//tr') for kalea, row in enumerate(rows): if kalea == 0: continue data = [x.text for x in row.findall('.//td')] try: if not data[1] is None: if urtea < 2008: pos = 12 aux = re.sub('[^0-9]', '', data[6]) try: pos = int(aux) except ValueError: pos = 12 else: pos = 0 emaitza = TaldeEmaitza(talde_izena=data[1], kalea=kalea, ziabogak=data[2:5], denbora=data[5], tanda=num + 1, posizioa=pos, tanda_postua=4) self.estropada.taldeak_add(emaitza) except TypeError as e: print(e) def calculate_tanda_posizioa(self): tanda_posizioak = [0] + [1] * 7 for pos, taldea in enumerate(sorted(self.estropada.sailkapena)): taldea.posizioa = pos + 1 taldea.tanda_postua = tanda_posizioak[taldea.tanda] tanda_posizioak[taldea.tanda] = tanda_posizioak[taldea.tanda] + 1 def parse_resume(self, document): sailkapenak = document.cssselect('#resultado table') tandaKopurua = len(sailkapenak) rows = sailkapenak[tandaKopurua - 1].findall('.//tr') tanda_posizioak = [0] + [1] * 7 for pos, row in enumerate(rows): if pos == 0: continue try: taldea = row.find('.//td[2]').text.strip() posizioa = pos print(posizioa) puntuak = row.find('.//td[4]').text.strip() for t in self.estropada.sailkapena: if re.match(t.talde_izena, taldea, re.I): try: t.posizioa = posizioa t.tanda_postua = tanda_posizioak[t.tanda] t.puntuazioa = int(puntuak) except Exception as e: print(e) t.posizioa = 1 t.tanda_postua = tanda_posizioak[t.tanda] t.puntuazioa = 0 tanda_posizioak[t.tanda] = tanda_posizioak[t.tanda] + 1 except Exception as e: logging.warn(self.estropada.izena) logging.info("Error parsing results", exec_info=True)
class EuskotrenParser(Parser): '''Base class to parse an Euskotren race result''' def __init__(self): pass def parse(self, *args): '''Parse a result and return an estropada object''' urla = args[0] document = self.get_content(*args) (estropadaName, estropadaDate, lekua) = self.parse_headings(document) opts = { 'urla': urla, 'lekua': lekua, 'data': estropadaDate, 'liga': 'euskotren' } self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document) self.parse_resume(document) return self.estropada def parse_headings(self, document): '''Parse headings table''' heading_three = document.cssselect('h3') data = '' if len(heading_three) > 0: name = heading_three[0].text.strip() estropada = name.split('(')[0].strip() quoted_text = re.findall('\(([^\)]+)', name) for t in quoted_text: for data_format in ['%Y-%m-%d', '%d-%m-%Y']: try: data = datetime.datetime.strptime(t, '%Y-%m-%d') except ValueError: pass if data == '': estropada = estropada + t heading_table = document.cssselect( 'table[summary="Regata Puntuable"] td') lekua = '' if heading_table: lekua = heading_table[1].text.strip() ordua = re.split('[.:]', heading_table[3].text.strip()) data_ordua = data.replace(hour=int(ordua[0], 10), minute=int(ordua[1], 10)) data_text = data_ordua.strftime('%Y-%m-%d %H:%M') else: data_text = data_ordua.strftime('%Y-%m-%d') return (estropada, data_text, lekua) def parse_tandas(self, document): numberOfHeats = document.find_class('tabla_tanda') for num, heat in enumerate(numberOfHeats): results = heat.findall('.//tbody//tr') for result in results: resultData = [x.text for x in result.findall('.//td')] if resultData[1] is not None: teamName = resultData[1].strip() # ziabogak = map(lambda s: s or '', resultData[2:5]) ziabogak = [ result if result is not None else '' for result in resultData[2:5] ] if resultData[5] is None: denbora = '' else: denbora = resultData[5] teamResult = TaldeEmaitza(talde_izena=teamName, kalea=int(resultData[0]), ziabogak=ziabogak, denbora=denbora, tanda=num + 1, tanda_postua=int(resultData[6]), posizioa=0) self.estropada.taldeak_add(teamResult) def parse_resume(self, document): sailkapena = document.cssselect( 'h3.clasificacion + .fondo_taula > .taula') if len(sailkapena) > 0: rows = sailkapena[0].findall('.//tbody//tr') for row in rows: position = row.find('.//td[1]').text_content() teamName = row.find('.//td[2]').text if teamName is not None: teamName = row.find('.//td[2]').text.strip() puntuazioa = row.find('.//td[7]').text.strip() for t in self.estropada.sailkapena: if t.talde_izena == teamName: try: t.posizioa = int(position) t.puntuazioa = int(puntuazioa) except: print("Errorea") t.posizioa = 1
def test_estropada(): izena = 'Test estropada' e = Estropada(izena) assert type(e) == Estropada assert e.izena == izena
class ArcParser(Parser): '''Base class to parse an ARC race result''' def __init__(self): pass def parse(self, *args): '''Parse a result and return an estropada object''' urla = args[0] document = self.get_content(*args) (estropadaName, estropadaDate, lekua, liga) = self.parse_headings(document) opts = {'urla': urla, 'data': estropadaDate, 'liga': liga, 'lekua': lekua} self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document) self.parse_resume(document) return self.estropada def parse_headings(self, document): '''Parse headings table''' liga_selector = document.cssselect('h1.seccion span span')[0].text.lower() if 'grupo 1' in liga_selector: liga_taldea = 'ARC1' else: liga_taldea = 'ARC2' heading_two = document.cssselect('.resultado h2') estropada = heading_two[0].text.strip() date_block = document.cssselect('li.fecha') hour_block = document.cssselect('li.hora') resume_block = document.cssselect('.articulo ul li') # Remove map span lekua = '' if len(resume_block) == 4: resume_block[3].cssselect('span')[0].drop_tree() lekua = resume_block[3].text_content().strip() date = date_block[0].text_content().strip(" \n").replace('Fecha', '').strip(" \n") new_date = self.parse_date(date) hour = hour_block[0].text_content().replace('Hora', '').strip() race_date = new_date + " " + hour return (estropada, race_date, lekua, liga_taldea) def parse_date(self, date): new_date = date.replace('Jun', '06') new_date = new_date.replace('Jul', '07') new_date = new_date.replace('Ago', '08') new_date = new_date.replace('Sept', '09') date_list = re.split(' ', new_date) (day, month, year) = date_list if int(day) < 10: day = '0' + day new_date = year + "-" + month + "-" + day return new_date def parse_tandas(self, document): tandas = document.cssselect('table.tanda') for num, text in enumerate(tandas): rows = text.findall('.//tbody//tr') for kalea, row in enumerate(rows): data = [x.text for x in row.findall('.//td')] taldea = row.find('.//span//a') emaitza = TaldeEmaitza(talde_izena=taldea.text.strip(), kalea=kalea + 1, ziabogak=data[1:4], denbora=data[4], tanda=num + 1) self.estropada.taldeak_add(emaitza) def parse_resume(self, document): sailkapena = document.find_class('clasificacion-regata') if len(sailkapena) > 0: rows = sailkapena[0].findall('.//tbody//tr') tanda_posizioak = [0] + [1] * 7 for pos, row in enumerate(rows): taldea = row.find('.//span//a').text.strip() try: puntuak = row.find('.//td[3]').text.strip() except: puntuak = 0 for t in self.estropada.sailkapena: if t.talde_izena == taldea: try: t.posizioa = pos + 1 t.tanda_postua = tanda_posizioak[t.tanda] t.puntuazioa = int(puntuak) except: t.posizioa = 1 t.tanda_postua = tanda_posizioak[t.tanda] t.puntuazioa = 0 tanda_posizioak[t.tanda] = tanda_posizioak[t.tanda] + 1
class ActParser(Parser): '''Base class to parse an ACT race result''' def __init__(self): pass def parse(self, *args): '''Parse a result and return an estropada object''' urla = args[0] document = self.get_content(*args) (estropadaName, estropadaDate, lekua, puntuagarria) = self.parse_headings(document) opts = { 'urla': urla, 'lekua': lekua, 'data': estropadaDate, 'liga': 'ACT', 'puntuagarria': puntuagarria } self.estropada = Estropada(estropadaName, **opts) self.parse_tandas(document) self.parse_resume(document) return self.estropada def calculate_points_positions(self): self.estropada.sailkapena.sort(key=lambda x: datetime.datetime.strptime(x.denbora, '%M:%S,%f')) for index, taldea in enumerate(self.estropada.sailkapena): taldea.posizioa = index + 1 taldea.puntuazioa = len(self.estropada.sailkapena) + 1 - taldea.posizioa def parse_headings(self, document): '''Parse table headings''' heading_three = document.cssselect('h3') data = '' puntuagarria = True if len(heading_three) > 0: name = heading_three[0].text.strip() puntuagarria_block = document.cssselect('p span.clase3, p span.clase1') if len(puntuagarria_block) > 0: puntuagarria_text = puntuagarria_block[0].text.strip().lower() puntuagarria = False if puntuagarria_text.startswith(('ez', 'no',)) else True puntuagarria_block = document.cssselect('p span.clase2') if len(puntuagarria_block) > 0: puntuagarria_text = puntuagarria_block[0].text.strip().lower() puntuagarria = False if puntuagarria_text.startswith('play') else True estropada = name.split('(')[0].strip() quoted_text = re.findall('\(([^\)]+)', name) for t in quoted_text: for data_format in ['%Y-%m-%d', '%d-%m-%Y']: try: data = datetime.datetime.strptime(t, data_format) except ValueError: pass if data == '': estropada = estropada + t heading_table = document.cssselect('table[summary="Regata Puntuable"] td') lekua = '' if heading_table: lekua = heading_table[1].text.strip() ordua = re.split('[.:]', heading_table[3].text.strip()) data_ordua = data.replace(hour=int(ordua[0], 10), minute=int(ordua[1], 10)) data_text = data_ordua.strftime('%Y-%m-%d %H:%M') else: data_text = data.strftime('%Y-%m-%d') return (estropada, data_text, lekua, puntuagarria) def parse_tandas(self, document): '''Parse race's paces tables''' tandas = document.find_class('tabla_tanda') for num, text in enumerate(tandas): rows = text.findall('.//tbody//tr') for row in rows: data = [x.text for x in row.findall('.//td')] kalea = int(data[0]) if data[1]: emaitza = TaldeEmaitza(talde_izena=data[1].strip(), kalea=kalea, ziabogak=data[2:5], denbora=data[5], tanda=num + 1, tanda_postua=int(data[6]), posizioa=0) self.estropada.taldeak_add(emaitza) def parse_resume(self, document): '''Parse race's resume table''' rank_table = '//table[@summary="Estropadaren sailkapena"]' try: sailkapena = document.xpath(rank_table) rows = sailkapena[-1].findall('.//tbody//tr') except: rows = [] for num, row in enumerate(rows): try: if num == 0: posizioa = row.find('.//td[1]//span').text.strip() else: posizioa = row.find('.//td[1]').text.strip() team = row.find('.//td[2]').text.strip() puntuak = row.find('.//td[7]').text.strip() for i, taldea in enumerate(self.estropada.sailkapena): if taldea.talde_izena == team: try: self.estropada.sailkapena[i].posizioa = int(posizioa, 10) self.estropada.sailkapena[i].puntuazioa = int(puntuak, 10) except: print(f'Ez dago posizio edo puntuazioarik {team} taldearentzat') except: return None