Spaces:
Running
Running
| import os | |
| import logging | |
| from flask import Flask, render_template, request, jsonify | |
| from flask_cors import CORS | |
| import json | |
| from datetime import datetime, date | |
| from scrapers.horoscope_scraper import HoroscopeScraper | |
| from scrapers.astrology_com_scraper import AstrologyComScraper | |
| from scrapers.horoscope_com_scraper import HoroscopeComScraper | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Create Flask app | |
| app = Flask(__name__) | |
| app.secret_key = os.environ.get("SESSION_SECRET", "dev_secret_key") | |
| # Enable CORS | |
| CORS(app) | |
| # Initialize scrapers | |
| scrapers = { | |
| "astrology.com": AstrologyComScraper(), | |
| "horoscope.com": HoroscopeComScraper(), | |
| } | |
| def index(): | |
| """Main page""" | |
| return render_template('simple_index.html') | |
| def health_check(): | |
| """Health check endpoint""" | |
| return jsonify({ | |
| "status": "ok", | |
| "message": "Horoscope API is running", | |
| "scrapers": list(scrapers.keys()) | |
| }) | |
| def scrape_horoscope(): | |
| """Scrape horoscope for a specific sign""" | |
| data = request.get_json() | |
| if not data: | |
| return jsonify({"error": "Missing request data"}), 400 | |
| sign = data.get('sign', '').lower() | |
| source = data.get('source', 'astrology.com') | |
| # Validate inputs | |
| if not sign: | |
| return jsonify({"error": "Missing 'sign' parameter"}), 400 | |
| if sign not in scrapers["astrology.com"].ZODIAC_SIGNS: | |
| return jsonify({"error": f"Invalid zodiac sign: {sign}"}), 400 | |
| if source not in scrapers: | |
| return jsonify({"error": f"Unknown source: {source}"}), 400 | |
| try: | |
| # Scrape horoscope | |
| scraper = scrapers[source] | |
| result = scraper.scrape_sign(scraper.base_url, sign) | |
| if result.get('success', False): | |
| return jsonify({ | |
| "success": True, | |
| "sign": sign, | |
| "source": source, | |
| "prediction": result.get('prediction', ''), | |
| "date": result.get('date', date.today().isoformat()), | |
| "scraped_at": datetime.now().isoformat() | |
| }) | |
| else: | |
| return jsonify({ | |
| "success": False, | |
| "error": result.get('error', 'Unknown error occurred') | |
| }), 500 | |
| except Exception as e: | |
| logger.error(f"Error scraping horoscope: {str(e)}") | |
| return jsonify({ | |
| "success": False, | |
| "error": f"Scraping failed: {str(e)}" | |
| }), 500 | |
| def scrape_all_horoscopes(): | |
| """Scrape horoscopes for all signs from all sources""" | |
| data = request.get_json() or {} | |
| results = {} | |
| # Get all zodiac signs | |
| signs = scrapers["astrology.com"].ZODIAC_SIGNS | |
| for sign in signs: | |
| results[sign] = {} | |
| for source_name, scraper in scrapers.items(): | |
| try: | |
| result = scraper.scrape_sign(scraper.base_url, sign) | |
| if result.get('success', False): | |
| results[sign][source_name] = { | |
| "success": True, | |
| "prediction": result.get('prediction', ''), | |
| "date": result.get('date', date.today().isoformat()), | |
| "scraped_at": datetime.now().isoformat() | |
| } | |
| else: | |
| results[sign][source_name] = { | |
| "success": False, | |
| "error": result.get('error', 'Unknown error') | |
| } | |
| except Exception as e: | |
| logger.error(f"Error scraping {sign} from {source_name}: {str(e)}") | |
| results[sign][source_name] = { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| return jsonify({ | |
| "success": True, | |
| "results": results, | |
| "scraped_at": datetime.now().isoformat() | |
| }) | |
| def consolidate_horoscope(): | |
| """Consolidate horoscope predictions using OpenAI""" | |
| data = request.get_json() | |
| if not data: | |
| return jsonify({"error": "Missing request data"}), 400 | |
| predictions = data.get('predictions', []) | |
| sign = data.get('sign', '').lower() | |
| if not predictions: | |
| return jsonify({"error": "No predictions provided"}), 400 | |
| if not sign: | |
| return jsonify({"error": "Missing 'sign' parameter"}), 400 | |
| # Check if OpenAI API key is available | |
| openai_api_key = os.environ.get("OPENAI_API_KEY") | |
| if not openai_api_key: | |
| return jsonify({ | |
| "error": "OpenAI API key not configured. Please provide OPENAI_API_KEY." | |
| }), 500 | |
| try: | |
| from openai import OpenAI | |
| client = OpenAI(api_key=openai_api_key) | |
| # Create prompt for consolidation | |
| sources_text = "" | |
| for i, pred in enumerate(predictions, 1): | |
| source = pred.get("source", f"Source {i}") | |
| prediction = pred.get("prediction", "No prediction available") | |
| sources_text += f"SOURCE {i} ({source}):\n{prediction}\n\n" | |
| prompt = f""" | |
| Please analyze and consolidate these daily horoscope predictions for {sign.upper()}. | |
| {sources_text} | |
| Create a single, coherent daily horoscope prediction that synthesizes the information from all sources. | |
| Focus on the common themes and advice while maintaining the mystical and guiding tone typical of horoscopes. | |
| The response should be 2-3 paragraphs long and should NOT mention the sources or that it's a consolidation. | |
| Respond with JSON in this format: | |
| {{ | |
| "consolidated_prediction": "The consolidated horoscope text..." | |
| }} | |
| """ | |
| # Call OpenAI API | |
| response = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[ | |
| {"role": "system", "content": "You are an expert astrologer specializing in synthesizing horoscope predictions."}, | |
| {"role": "user", "content": prompt} | |
| ], | |
| response_format={"type": "json_object"}, | |
| temperature=0.7 | |
| ) | |
| # Parse the response | |
| content = response.choices[0].message.content | |
| if content: | |
| result = json.loads(content) | |
| else: | |
| result = {"consolidated_prediction": "Unable to generate consolidated prediction."} | |
| return jsonify({ | |
| "success": True, | |
| "sign": sign, | |
| "consolidated_prediction": result.get("consolidated_prediction", ""), | |
| "sources_count": len(predictions), | |
| "consolidated_at": datetime.now().isoformat() | |
| }) | |
| except ImportError: | |
| return jsonify({ | |
| "error": "OpenAI library not available. Please install: pip install openai" | |
| }), 500 | |
| except Exception as e: | |
| logger.error(f"Error consolidating horoscopes: {str(e)}") | |
| return jsonify({ | |
| "error": f"Consolidation failed: {str(e)}" | |
| }), 500 | |
| def get_zodiac_signs(): | |
| """Get list of zodiac signs""" | |
| return jsonify({ | |
| "signs": scrapers["astrology.com"].ZODIAC_SIGNS | |
| }) | |
| if __name__ == "__main__": | |
| logger.info("Starting simple horoscope API server") | |
| app.run(host="0.0.0.0", port=5000, debug=True) |