├── README.md ├── __pycache__ └── minigroqqle.cpython-312.pyc ├── api.py ├── minigroqqle.py ├── requirements.txt ├── src ├── MiniGroqqle.md └── custom_instructions.txt └── test.py /README.md: -------------------------------------------------------------------------------- 1 | # MiniGroqqle: Lightweight Web Search for Python 2 | ![image](https://github.com/user-attachments/assets/6f4ba625-7d9e-4383-b354-3c3c17b970e9) 3 | 4 | 5 | MiniGroqqle is a minimalist web search component that allows Python developers to easily integrate web search capabilities into their applications. With just a few lines of code, you can perform Google searches and retrieve structured results. 6 | 7 | ## Features 8 | 9 | - Simple and lightweight 10 | - Easy to integrate 11 | - Customizable number of search results 12 | - Returns structured data (title, URL, and description) for each result 13 | 14 | - VIDEO: https://youtu.be/Y3srmpL8klY 15 | 16 | ## JSON Output 17 | 18 | MiniGroqqle now supports JSON output for easy integration with JSON-based applications. To get results in JSON format, simply set the `json_output` parameter to `True` when calling the `search` method: 19 | 20 | ```python 21 | from minigroqqle import MiniGroqqle 22 | 23 | searcher = MiniGroqqle(num_results=3) 24 | results = searcher.search("Python programming", json_output=True) 25 | 26 | print(results) # This will print a JSON string 27 | ``` 28 | 29 | When using JSON output, the results will be returned as a JSON-formatted string instead of a list of dictionaries. This makes it easy to parse and use the results in various applications or to send them over network protocols. 30 | 31 | ## Installation 32 | 33 | To install MiniGroqqle and its dependencies, run: 34 | 35 | ```bash 36 | pip install requests beautifulsoup4 37 | ``` 38 | 39 | Then, download the `minigroqqle.py` file and place it in your project directory. 40 | 41 | ## QuickStart 42 | 43 | Here's how to quickly get started with MiniGroqqle in your Python application: 44 | 45 | 1. Import the MiniGroqqle class: 46 | 47 | ```python 48 | from minigroqqle import MiniGroqqle 49 | ``` 50 | 51 | 2. Create an instance of MiniGroqqle: 52 | 53 | ```python 54 | searcher = MiniGroqqle(num_results=5) # Specify the number of results you want 55 | ``` 56 | 57 | 3. Perform a search: 58 | 59 | ```python 60 | results = searcher.search("Python programming") 61 | ``` 62 | 63 | 4. Process the results: 64 | 65 | ```python 66 | for result in results: 67 | print(f"Title: {result['title']}") 68 | print(f"URL: {result['url']}") 69 | print(f"Description: {result['description']}") 70 | print("---") 71 | ``` 72 | 73 | That's it! You now have web search capabilities in your Python application. 74 | 75 | ## Example 76 | 77 | Here's a complete example that you can run: 78 | 79 | ```python 80 | from minigroqqle import MiniGroqqle 81 | 82 | searcher = MiniGroqqle(num_results=3) 83 | results = searcher.search("Python programming") 84 | 85 | for result in results: 86 | print(f"Title: {result['title']}") 87 | print(f"URL: {result['url']}") 88 | print(f"Description: {result['description']}") 89 | print("---") 90 | ``` 91 | 92 | ## API Usage 93 | 94 | MiniGroqqle now includes an API endpoint to perform searches and return results in JSON format. The API is built using Flask and provides a `/search` endpoint that accepts a query parameter. 95 | 96 | ### Running the API 97 | 98 | To run the API, first install the required dependencies: 99 | 100 | ```bash 101 | pip install Flask 102 | ``` 103 | 104 | Then, create a file named `api.py` with the following content: 105 | 106 | ```python 107 | from flask import Flask, request, jsonify 108 | from minigroqqle import MiniGroqqle 109 | 110 | app = Flask(__name__) 111 | 112 | @app.route('/search', methods=['GET']) 113 | def search(): 114 | query = request.args.get('query') 115 | if not query: 116 | return jsonify({"error": "Missing query parameter"}), 400 117 | 118 | searcher = MiniGroqqle(num_results=5) 119 | results = searcher.search(query, json_output=True) 120 | return results 121 | 122 | if __name__ == '__main__': 123 | app.run(debug=True) 124 | ``` 125 | 126 | To start the API, run the following command: 127 | 128 | ```bash 129 | python api.py 130 | ``` 131 | 132 | The API will be available at `http://127.0.0.1:5000/search`. 133 | 134 | ### Using the API 135 | 136 | To use the API, send a GET request to the `/search` endpoint with a `query` parameter. For example: 137 | 138 | ```bash 139 | curl "http://127.0.0.1:5000/search?query=Python+programming" 140 | ``` 141 | 142 | The API will return the search results in JSON format. 143 | 144 | ## Contributing 145 | 146 | We welcome contributions to MiniGroqqle! Please feel free to submit issues, fork the repository and send pull requests! 147 | 148 | ## License 149 | 150 | MiniGroqqle is released under the MIT License. Mention J. Gravelle in your code and documentation if you borrow any of this code. He's kinda full of himself... 151 | 152 | ## Disclaimer 153 | 154 | This tool is for educational purposes only. Make sure to comply with the terms of service of the search engine you're querying. Be mindful of rate limiting and respect the usage policies of the services you're accessing. 155 | -------------------------------------------------------------------------------- /__pycache__/minigroqqle.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgravelle/MiniGroqqle/6fdae899a68b4ba3e3dd1a25caaae19119483fa7/__pycache__/minigroqqle.cpython-312.pyc -------------------------------------------------------------------------------- /api.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | from minigroqqle import MiniGroqqle 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route('/search', methods=['GET']) 7 | def search(): 8 | query = request.args.get('query') 9 | if not query: 10 | return jsonify({"error": "Missing query parameter"}), 400 11 | 12 | searcher = MiniGroqqle(num_results=5) 13 | results = searcher.search(query, json_output=True) 14 | return results 15 | 16 | if __name__ == '__main__': 17 | app.run(debug=True) 18 | -------------------------------------------------------------------------------- /minigroqqle.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | from bs4 import BeautifulSoup 5 | from typing import List, Dict, Any, Union 6 | from urllib.parse import quote_plus 7 | 8 | class MiniGroqqle: 9 | def __init__(self, num_results: int = 10): 10 | self.num_results = num_results 11 | self.headers = { 12 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 13 | } 14 | 15 | def search(self, query: str, json_output: bool = False) -> Union[List[Dict[str, Any]], str]: 16 | encoded_query = quote_plus(query) 17 | search_url = f"https://www.google.com/search?q={encoded_query}&num={self.num_results * 2}" 18 | 19 | try: 20 | response = requests.get(search_url, headers=self.headers, timeout=10) 21 | response.raise_for_status() 22 | soup = BeautifulSoup(response.text, 'html.parser') 23 | 24 | search_results = [] 25 | for g in soup.find_all('div', class_='g'): 26 | anchor = g.find('a') 27 | title = g.find('h3').text if g.find('h3') else 'No title' 28 | url = anchor.get('href', '') if anchor else '' 29 | 30 | description = '' 31 | description_div = g.find('div', class_=['VwiC3b', 'yXK7lf']) 32 | if description_div: 33 | description = description_div.get_text(strip=True) 34 | else: 35 | description = g.get_text(strip=True) 36 | 37 | if url.startswith('http'): 38 | search_results.append({ 39 | 'title': title, 40 | 'description': description, 41 | 'url': url 42 | }) 43 | 44 | results = search_results[:self.num_results] 45 | 46 | if json_output: 47 | return json.dumps(results, indent=2) 48 | else: 49 | return results 50 | except requests.RequestException as e: 51 | error_message = f"Error performing search: {str(e)}" 52 | if json_output: 53 | return json.dumps({"error": error_message}) 54 | else: 55 | return [{"error": error_message}] 56 | 57 | # Example usage 58 | if __name__ == "__main__": 59 | searcher = MiniGroqqle(num_results=5) 60 | results = searcher.search("Python programming") 61 | for result in results: 62 | print(f"Title: {result['title']}") 63 | print(f"URL: {result['url']}") 64 | print(f"Description: {result['description']}") 65 | print("---") -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | requests 3 | Flask 4 | -------------------------------------------------------------------------------- /src/MiniGroqqle.md: -------------------------------------------------------------------------------- 1 | # minigroqqle.py 2 | 3 | ```python 4 | import json 5 | import requests 6 | 7 | from bs4 import BeautifulSoup 8 | from typing import List, Dict, Any, Union 9 | from urllib.parse import quote_plus 10 | 11 | class MiniGroqqle: 12 | def __init__(self, num_results: int = 10): 13 | self.num_results = num_results 14 | self.headers = { 15 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 16 | } 17 | 18 | def search(self, query: str, json_output: bool = False) -> Union[List[Dict[str, Any]], str]: 19 | encoded_query = quote_plus(query) 20 | search_url = f"https://www.google.com/search?q={encoded_query}&num={self.num_results * 2}" 21 | 22 | try: 23 | response = requests.get(search_url, headers=self.headers, timeout=10) 24 | response.raise_for_status() 25 | soup = BeautifulSoup(response.text, 'html.parser') 26 | 27 | search_results = [] 28 | for g in soup.find_all('div', class_='g'): 29 | anchor = g.find('a') 30 | title = g.find('h3').text if g.find('h3') else 'No title' 31 | url = anchor.get('href', '') if anchor else '' 32 | 33 | description = '' 34 | description_div = g.find('div', class_=['VwiC3b', 'yXK7lf']) 35 | if description_div: 36 | description = description_div.get_text(strip=True) 37 | else: 38 | description = g.get_text(strip=True) 39 | 40 | if url.startswith('http'): 41 | search_results.append({ 42 | 'title': title, 43 | 'description': description, 44 | 'url': url 45 | }) 46 | 47 | results = search_results[:self.num_results] 48 | 49 | if json_output: 50 | return json.dumps(results, indent=2) 51 | else: 52 | return results 53 | except requests.RequestException as e: 54 | error_message = f"Error performing search: {str(e)}" 55 | if json_output: 56 | return json.dumps({"error": error_message}) 57 | else: 58 | return [{"error": error_message}] 59 | 60 | # Example usage 61 | if __name__ == "__main__": 62 | searcher = MiniGroqqle(num_results=5) 63 | results = searcher.search("Python programming") 64 | for result in results: 65 | print(f"Title: {result['title']}") 66 | print(f"URL: {result['url']}") 67 | print(f"Description: {result['description']}") 68 | print("---") 69 | ``` 70 | 71 | # test.py 72 | 73 | ```python 74 | import sys 75 | import json 76 | from minigroqqle import MiniGroqqle 77 | 78 | def print_results(results): 79 | if isinstance(results, str): 80 | # Results are in JSON format 81 | parsed_results = json.loads(results) 82 | if "error" in parsed_results: 83 | print(f"Error: {parsed_results['error']}") 84 | else: 85 | for i, result in enumerate(parsed_results, 1): 86 | print(f"Result {i}:") 87 | print(f"Title: {result['title']}") 88 | print(f"URL: {result['url']}") 89 | print(f"Description: {result['description']}") 90 | print("---") 91 | else: 92 | # Results are in list format 93 | if results and "error" in results[0]: 94 | print(f"Error: {results[0]['error']}") 95 | else: 96 | for i, result in enumerate(results, 1): 97 | print(f"Result {i}:") 98 | print(f"Title: {result['title']}") 99 | print(f"URL: {result['url']}") 100 | print(f"Description: {result['description']}") 101 | print("---") 102 | 103 | def main(): 104 | if len(sys.argv) < 2: 105 | print("Usage: python test.py [--json]") 106 | sys.exit(1) 107 | 108 | json_output = "--json" in sys.argv 109 | search_query = " ".join(arg for arg in sys.argv[1:] if arg != "--json") 110 | 111 | searcher = MiniGroqqle(num_results=5) 112 | results = searcher.search(search_query, json_output=json_output) 113 | 114 | if json_output: 115 | print(results) # Print raw JSON string 116 | else: 117 | print_results(results) 118 | 119 | if __name__ == "__main__": 120 | main() 121 | ``` 122 | 123 | -------------------------------------------------------------------------------- /src/custom_instructions.txt: -------------------------------------------------------------------------------- 1 | MiniGroqqle is a minimalist web search component that allows Python developers to easily integrate web search capabilities into their applications. With just a few lines of code, you can perform Google searches and retrieve structured results. 2 | 3 | Please act as an expert Python programmer and software engineer. The attached MiniGroqqle.md file contains the complete and up-to-date codebase for our application. Your task is to thoroughly analyze the codebase, understand its programming flow and logic, and provide detailed insights, suggestions, and solutions to enhance the application's performance, efficiency, readability, and maintainability. 4 | 5 | We highly value responses that demonstrate a deep understanding of the code. Please ensure your recommendations are thoughtful, well-analyzed, and contribute positively to the project's success. Your expertise is crucial in helping us improve and upgrade our application. 6 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | from minigroqqle import MiniGroqqle 4 | 5 | def print_results(results): 6 | if isinstance(results, str): 7 | # Results are in JSON format 8 | parsed_results = json.loads(results) 9 | if "error" in parsed_results: 10 | print(f"Error: {parsed_results['error']}") 11 | else: 12 | for i, result in enumerate(parsed_results, 1): 13 | print(f"Result {i}:") 14 | print(f"Title: {result['title']}") 15 | print(f"URL: {result['url']}") 16 | print(f"Description: {result['description']}") 17 | print("---") 18 | else: 19 | # Results are in list format 20 | if results and "error" in results[0]: 21 | print(f"Error: {results[0]['error']}") 22 | else: 23 | for i, result in enumerate(results, 1): 24 | print(f"Result {i}:") 25 | print(f"Title: {result['title']}") 26 | print(f"URL: {result['url']}") 27 | print(f"Description: {result['description']}") 28 | print("---") 29 | 30 | def main(): 31 | if len(sys.argv) < 2: 32 | print("Usage: python test.py [--json]") 33 | sys.exit(1) 34 | 35 | json_output = "--json" in sys.argv 36 | search_query = " ".join(arg for arg in sys.argv[1:] if arg != "--json") 37 | 38 | searcher = MiniGroqqle(num_results=5) 39 | results = searcher.search(search_query, json_output=json_output) 40 | 41 | if json_output: 42 | print(results) # Print raw JSON string 43 | else: 44 | print_results(results) 45 | 46 | if __name__ == "__main__": 47 | main() --------------------------------------------------------------------------------