Skip to content
This repository has been archived by the owner on Nov 20, 2022. It is now read-only.

Commit

Permalink
Merge branch 'feature/ipp-bistro' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
srehwald committed Nov 26, 2017
2 parents 39a58c5 + a70d711 commit f4ed55d
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 4 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Simple static API for the canteens of the [Studentenwerk München](http://www.st
- Mensa Arcisstraße (mensa-arcisstrasse)
- StuBistro Großhadern (stubistro-grosshadern)
- FMI Bistro Garching (fmi-bistro)
- IPP Bistro Garching (ipp-bistro)

## Usage

Expand All @@ -27,10 +28,10 @@ The JSON files are produced by the tool shown in this repository. Hence, it is e
```
$ python src/main.py -h
usage: main.py [-h] [-d DATE] [-j PATH]
{mensa-garching,mensa-arcisstrasse,stubistro-grosshadern,fmi-bistro}
{mensa-garching,mensa-arcisstrasse,stubistro-grosshadern,fmi-bistro,ipp-bistro}
positional arguments:
{mensa-garching,mensa-arcisstrasse,stubistro-grosshadern}
{mensa-garching,mensa-arcisstrasse,stubistro-grosshadern,fmi-bistro,ipp-bistro}
the location you want to eat at
optional arguments:
Expand Down
1 change: 1 addition & 0 deletions scripts/parse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ python src/main.py mensa-garching -j ./dist/mensa-garching
python src/main.py mensa-arcisstrasse -j ./dist/mensa-arcisstrasse
python src/main.py stubistro-grosshadern -j ./dist/stubistro-grosshadern
python src/main.py fmi-bistro -j ./dist/fmi-bistro
python src/main.py ipp-bistro -j ./dist/ipp-bistro
tree dist/
2 changes: 1 addition & 1 deletion src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def parse_cli_args():
parser = argparse.ArgumentParser()
parser.add_argument('location', choices=['mensa-garching', 'mensa-arcisstrasse', 'stubistro-grosshadern',
'fmi-bistro'],
'fmi-bistro', 'ipp-bistro'],
help='the location you want to eat at')
parser.add_argument('-d', '--date', help='date (DD.MM.YYYY) of the day of which you want to get the menu')
parser.add_argument('-j', '--jsonify',
Expand Down
2 changes: 2 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def get_menu_parsing_strategy(location):
parser = menu_parser.StudentenwerkMenuParser()
elif location == "fmi-bistro":
parser = menu_parser.FMIBistroMenuParser()
elif location == "ipp-bistro":
parser = menu_parser.IPPBistroMenuParser()

return parser

Expand Down
97 changes: 97 additions & 0 deletions src/menu_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,100 @@ def get_menus(self, text, year, week_number):
menus[date] = menu

return menus


class IPPBistroMenuParser(MenuParser):
url = "http://konradhof-catering.de/ipp/"
weekday_positions = {"mon": 1, "tue": 2, "wed": 3, "thu": 4, "fri": 5}
price_regex = r"\d+,\d+\s\€[^\)]"
dish_regex = r".+?\d+,\d+\s\€[^\)]"

def parse(self, location):
page = requests.get(self.url)
# get html tree
tree = html.fromstring(page.content)
# get url of current pdf menu
xpath_query = tree.xpath("//a[contains(text(), 'KW-')]/@href")
pdf_url = xpath_query[0] if len(xpath_query) >= 1 else None

if pdf_url is None:
return None

# Example PDF-name: KW-48_27.11-01.12.10.2017-3.pdf
pdf_name = pdf_url.split("/")[-1]
year = int(pdf_name.replace(".pdf","").split(".")[-1].split("-")[0])
week_number = int(pdf_name.split("_")[0].replace("KW-","").lstrip("0"))

with tempfile.NamedTemporaryFile() as temp_pdf:
# download pdf
response = requests.get(pdf_url)
temp_pdf.write(response.content)
with tempfile.NamedTemporaryFile() as temp_txt:
# convert pdf to text by calling pdftotext; only convert first page to txt (-l 1)
call(["pdftotext", "-l", "1", "-layout", temp_pdf.name, temp_txt.name])
with open(temp_txt.name, 'r') as myfile:
# read generated text file
data = myfile.read()
menus = self.get_menus(data, year, week_number)
return menus

def get_menus(self, text, year, week_number):
menus = {}
lines = text.splitlines()
count = 0
# remove headline etc.
for line in lines:
if line.replace(" ", "").replace("\n", "").lower() == "montagdienstagmittwochdonnerstagfreitag":
break

count += 1

lines = lines[count:]
weekdays = lines[0]
lines = lines[3:]

positions = [(a.start(), a.end()) for a in list(re.finditer('Tagessuppe siehe Aushang', lines[0]))]
if len(positions) != 5:
# TODO handle special cases (e.g. that bistro is closed)
return None

pos_mon = positions[0][0]
pos_tue = positions[1][0]
pos_wed = positions[2][0]
pos_thu = positions[3][0]
pos_fri = positions[4][0]

lines_weekdays = {"mon": "", "tue": "", "wed": "", "thu": "", "fri": ""}
for line in lines[2:]:
lines_weekdays["mon"] += " " + line[pos_mon:pos_tue].replace("\n", " ")
lines_weekdays["tue"] += " " + line[pos_tue:pos_wed].replace("\n", " ")
lines_weekdays["wed"] += " " + line[pos_wed:pos_thu].replace("\n", " ")
lines_weekdays["thu"] += " " + line[pos_thu:pos_fri].replace("\n", " ")
lines_weekdays["fri"] += " " + line[pos_fri:].replace("\n", " ")

for key in lines_weekdays:
# get rid of two-character umlauts (e.g. SMALL_LETTER_A+COMBINING_DIACRITICAL_MARK_UMLAUT)
lines_weekdays[key] = unicodedata.normalize("NFKC", lines_weekdays[key])
# remove multi-whitespaces
lines_weekdays[key] = ' '.join(lines_weekdays[key].split())
# get all dish including name and price
dish_names = re.findall(self.dish_regex, lines_weekdays[key] + " ")
# get dish prices
prices = re.findall(self.price_regex, ' '.join(dish_names))
# convert prices to float
prices = [float(price.replace("€", "").replace(",", ".").strip()) for price in prices]
# remove price and commas from dish names
dish_names = [re.sub(self.price_regex, "", dish).strip() for dish in dish_names]
# create list of Dish objects
dishes = [Dish(dish_name, price) for (dish_name, price) in list(zip(dish_names, prices))]
# get date from year, week number and current weekday
# https://stackoverflow.com/questions/17087314/get-date-from-week-number
date_str = "%d-W%d-%d" % (year, week_number, self.weekday_positions[key])
date = datetime.strptime(date_str, "%Y-W%W-%w").date()
# create new Menu object and add it to dict
menu = Menu(date, dishes)
# remove duplicates
menu.remove_duplicates()
menus[date] = menu

return menus
60 changes: 60 additions & 0 deletions src/test/assets/ipp/KW-47_20.11-24.11.2017-1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
KONRADHOF CATERING - Betriebskantine IPP

Speiseplan KW 47 - 20.November bis 24. November 2017

Montag Dienstag Mittwoch Donnerstag Freitag


Tagessuppe siehe Aushang Tagessuppe siehe Aushang Tagessuppe siehe Aushang Tagessuppe siehe Aushang Tagessuppe siehe Aushang
Suppentopf Preis ab 0,70 € Preis ab 0,70 € Preis ab 0,70 € Preis ab 0,70 € Preis ab 0,70 €



Gebratene Mediterrane Frittata
Weißkohl-Kartoffelpfanne mit Zucchini, Kartoffeln, Nudelpfanne
Gefüllter Germknödel Erbseneintopf
Veggie mit gerösteten Paprika, mit Gemüsesauce
mit Vanillesauce (mit Wienerle 4,20 €)
Sonnenblumenkernen kleiner Salatbeilage und (auf Wunsch mit Reibekäse)
Joghurt-Limetten Dip
3,50 € 3,50 € 3,50 € 3,50 € 3,50 €




Ofengulasch vom Rind Frischer Bayrischer
Jägerschnitzel Matjes
mit Kürbis und Pflaumen, Hackbraten mit Schweinenackenbraten vom
Traditionelle Küche mit Spätzle "Hausfrauen Art"
dazu Rigatoni Zigeunersauce und Reis Brett geschnitten dazu Kartoffel-
oder Reis mit Salzkartoffeln
Gurkensalat
5,50 € 4,80 € 4,80 € 4,50 € 5,20 €



"Palek Tofu" "Enchilada Verdura",
Vegetarisch gefüllte "Farfalle Rustico"
Gebratener Tofu mit Spinat, überbackene Weizentortilla, Currygeschnetzeltes
Tortelli mit mit Champignons, Schinken
Internationale Küche Ingwer, gefüllt von der Pute mit Früchten
leichter Zitronen-Buttersauce Tomaten und Peperoni
Curry-Sahnesauce und mit Hähnchenfleisch, und Reis
und gehobeltem Parmesan (auf Wunsch mit Reibekäse)
Basmatireis Sauerrahm, Kidneybohnen,
5,20 € 4,80 € 4,60 € Mais, dazu 5,90 € 4,90 €



"Bami Goreng"
Gebratene Hähnchenbrust
indonesische Bratnudeln mit
auf Fenchelgemüse, dazu Rumpsteak mit "Lamm Palak" mit Honig-Kassler
Gemüse, Huhn,
Specials Kräuterreis und Balsamico Pilzen Spinat und Curry mit Apfel-Spitzkohl und
Schweinefleisch
Orangensauce und Wedges (mittelscharf), dazu Reis Kartoffelspalten
und Pilzen, dazu Honig-Chili-
Dip
6,90 € 6,90 € 7,90 € 6,90 € 6,20 €

Loading

0 comments on commit f4ed55d

Please sign in to comment.