from flask import Flask, render_template, request, jsonify import mysql.connector import requests from bs4 import BeautifulSoup import json from datetime import datetime import re import urllib3 # 禁用SSL警告 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) app = Flask(__name__) # Database configuration from DB_connection.txt DB_CONFIG = { 'host': 'mysql.theaken.com', 'port': 33306, 'database': 'db_A019', 'user': 'A019', 'password': '9wvKEkxBzVca' } def get_db_connection(): """Establish database connection""" try: conn = mysql.connector.connect(**DB_CONFIG) return conn except mysql.connector.Error as e: print(f"Database connection error: {e}") return None def create_menu_table(): """Create menu_items table if not exists""" conn = get_db_connection() if conn: try: cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS menu_items ( Id INTEGER AUTO_INCREMENT PRIMARY KEY, main_course VARCHAR(50) NOT NULL, side_dish VARCHAR(50), addon VARCHAR(50), is_active BOOLEAN NOT NULL ) """) conn.commit() print("Menu table created or already exists") except mysql.connector.Error as e: print(f"Error creating table: {e}") finally: conn.close() def scrape_menu_data(): """Scrape menu data from the target URL""" url = "https://club.panjit.com.tw/back/menu/menu.php?1672970133&indexselectid=1" try: # Bypass SSL verification for the target website response = requests.get(url, timeout=10, verify=False) response.raise_for_status() soup = BeautifulSoup(response.content, 'html.parser') # 根據實際網站結構解析菜單資料 menu_items = [] # 查找菜單表格或列表 menu_tables = soup.find_all('table') menu_lists = soup.find_all(['ul', 'ol']) # 如果找到表格結構 if menu_tables: for table in menu_tables: rows = table.find_all('tr') for row in rows: cells = row.find_all('td') if len(cells) >= 2: # 至少有名稱和價格 name = cells[0].get_text(strip=True) price_text = cells[1].get_text(strip=True) # 提取價格數字 price = 0.0 try: # 從文字中提取數字 price_match = re.search(r'\d+', price_text) if price_match: price = float(price_match.group()) except: pass if name and price > 0: menu_items.append({ 'name': name, 'category': '主餐', 'price': price, 'description': f'{name} - 美味餐點', 'image_url': f'/static/images/{name.replace(" ", "_").lower()}.jpg' }) # 如果找到列表結構 elif menu_lists: for menu_list in menu_lists: items = menu_list.find_all('li') for item in items: text = item.get_text(strip=True) if text and any(char.isdigit() for char in text): # 嘗試解析項目名稱和價格 # 尋找價格模式 price_match = re.search(r'(\$|NT\$|\$)?\s*(\d+)', text) if price_match: price = float(price_match.group(2)) name = re.sub(r'(\$|NT\$|\$)?\s*\d+', '', text).strip() if name and price > 0: menu_items.append({ 'name': name, 'category': '餐點', 'price': price, 'description': f'{name} - 精選美食', 'image_url': f'/static/images/{name.replace(" ", "_").lower()}.jpg' }) # 如果以上方法都沒找到,使用備用方案:搜尋包含菜單文字的div或span if not menu_items: # 尋找可能包含菜單項目的元素 possible_menu_elements = soup.find_all(['div', 'span', 'p']) for elem in possible_menu_elements: text = elem.get_text(strip=True) if text and len(text) > 3 and any(char.isdigit() for char in text): price_match = re.search(r'(\$|NT\$|\$)?\s*(\d+)', text) if price_match: price = float(price_match.group(2)) name = re.sub(r'(\$|NT\$|\$)?\s*\d+.*', '', text).strip() if name and price > 0 and len(name) > 1: menu_items.append({ 'name': name, 'category': '餐點', 'price': price, 'description': f'{name} - 餐廳推薦', 'image_url': f'/static/images/{name.replace(" ", "_").lower()}.jpg' }) # 如果仍然沒有找到菜單項目,使用範例資料 if not menu_items: menu_items = [ { 'name': '經典牛肉麵', 'category': '主食', 'price': 120.00, 'description': '傳統台灣牛肉麵,湯頭濃郁', 'image_url': '/static/images/beef_noodle.jpg' }, { 'name': '雞腿飯', 'category': '主食', 'price': 95.00, 'description': '香煎雞腿配時蔬', 'image_url': '/static/images/chicken_rice.jpg' }, { 'name': '蔬菜沙拉', 'category': '前菜', 'price': 65.00, 'description': '新鮮時蔬搭配特製醬料', 'image_url': '/static/images/salad.jpg' }, { 'name': '紅燒獅子頭', 'category': '主餐', 'price': 150.00, 'description': '傳統江浙菜,肉質鮮嫩', 'image_url': '/static/images/lion_head.jpg' }, { 'name': '炒青菜', 'category': '蔬菜', 'price': 60.00, 'description': '時令蔬菜清炒', 'image_url': '/static/images/vegetable.jpg' } ] return menu_items except requests.RequestException as e: print(f"Error scraping menu data: {e}") # 返回範例資料作為備用 return [ { 'name': '經典牛肉麵', 'category': '主食', 'price': 120.00, 'description': '傳統台灣牛肉麵,湯頭濃郁', 'image_url': '/static/images/beef_noodle.jpg' }, { 'name': '雞腿飯', 'category': '主食', 'price': 95.00, 'description': '香煎雞腿配時蔬', 'image_url': '/static/images/chicken_rice.jpg' } ] def insert_menu_data(): """Insert sample menu items into database""" conn = get_db_connection() if conn: try: cursor = conn.cursor() # Clear existing data cursor.execute("DELETE FROM menu_items") # Insert sample data that matches the new table structure sample_menu_items = [ ('經典牛肉麵', '手工麵條', '酸菜湯', True), ('香煎雞腿飯', '時令蔬菜', '玉米濃湯', True), ('紅燒獅子頭', '白飯', '紫菜蛋花湯', True), ('蔬菜炒麵', None, '味噌湯', True), ('烤鮭魚排', '馬鈴薯泥', '南瓜湯', True) ] insert_query = """ INSERT INTO menu_items (main_course, side_dish, addon, is_active) VALUES (%s, %s, %s, %s) """ for item in sample_menu_items: cursor.execute(insert_query, item) conn.commit() print(f"Inserted {len(sample_menu_items)} menu items") except mysql.connector.Error as e: print(f"Error inserting menu data: {e}") finally: conn.close() @app.route('/') def index(): """Main page - display menu items""" conn = get_db_connection() menu_items = [] if conn: try: cursor = conn.cursor(dictionary=True) cursor.execute("SELECT * FROM menu_items ORDER BY category, name") menu_items = cursor.fetchall() except mysql.connector.Error as e: print(f"Error fetching menu items: {e}") finally: conn.close() return render_template('index.html', menu_items=menu_items) @app.route('/api/menu') def api_menu(): """API endpoint to get menu items""" conn = get_db_connection() menu_items = [] if conn: try: cursor = conn.cursor(dictionary=True) cursor.execute("SELECT * FROM menu_items ORDER BY category, name") menu_items = cursor.fetchall() except mysql.connector.Error as e: print(f"Error fetching menu items: {e}") finally: conn.close() return jsonify(menu_items) @app.route('/init') def initialize(): """Initialize database with menu data""" create_menu_table() insert_menu_data() return "Database initialized with sample menu data" if __name__ == '__main__': # Initialize database on startup create_menu_table() # Check if menu items exist, if not, insert sample data conn = get_db_connection() if conn: try: cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM menu_items") count = cursor.fetchone()[0] if count == 0: insert_menu_data() except mysql.connector.Error as e: print(f"Error checking menu items: {e}") finally: conn.close() app.run(debug=True, port=5000)