Home
Tell us the role you need →
Artificial IntelligenceGemini 3Data ExtractionAutomationPythonAI ToolsData EngineeringMachine LearningWeb ScrapingProductivity

Real-Time AI Data Extraction with Gemini 3: From Search to Verified Excel Output

AAalam TeamMarch 23, 20268 min read

Building with Gemini 3 

Implementing Real-Time Search Grounding in 2026 

1. Introduction 

By 2026, artificial intelligence models can generate fluent, human-like responses. However, the real challenge for production-grade systems is no longer generation quality — it is data accuracy, freshness, and verifiability. 

For use cases such as: 

  • extracting hospital contact details 

  • validating public directories 

  • enriching CRM systems 

traditional AI approaches frequently fail due to: 

  • outdated data 

  • hallucinated contact information 

  • lack of source verification 

This article demonstrates how Gemini 3 Real-Time Search Grounding can be used to extract verified hospital details across Africa, export the results to Excel, and maintain audit-ready outputs. 

2. What Is Real-Time Search Grounding? 

Real-time search grounding allows Gemini 3 to: 

  • search the web at request time 

  • retrieve live, authoritative sources 

  • constrain its response strictly to retrieved data 

Unlike traditional RAG (Retrieval-Augmented Generation), this approach: 

  • does not require a vector database 

  • avoids stale document repositories 

  • minimizes hallucination for public data 

This makes it particularly suitable for dynamic, real-world datasets such as hospital directories. 

3. Use Case Overview 

Objective 

Extract verified contact information for 20 hospitals across Africa, including: 

  • Hospital Name 

  • Email Address 

  • Contact Number 

  • Physical Address 

  • Country 

Output Format 

  • Structured JSON (from Gemini 3) 

  • Exported Excel file for validation and reporting 

 

4. Solution Architecture 

The implementation follows a simple and reliable pipeline: 

User Prompt 

   ↓ 

Gemini 3 with Live Google Search 

   ↓ 

Grounded & Verified Reasoning 

   ↓ 

Structured JSON Output 

   ↓ 

Excel Export 

 This architecture ensures that: 

  • all data is sourced live 

  • unverifiable fields are returned as null 

  • no assumptions or fabricated values are introduced 

6. Environment Requirements 

Create a file named requirements.txt: 

google-genai 

pandas 

openpyxl 

These libraries handle: 

  • Gemini 3 API interaction 

  • structured data processing 

  • Excel file generation 

7. Implementation Code 

main.py 

from google import genai 

from google.genai import types 

import pandas as pd 

from typing import List, Dict 

import json 

import re 

import time 

# Configure API key 

API_KEY = "your_api_key_here" 

client = genai.Client(api_key=API_KEY) 

 

def extract_hospital_details(query: str, location: str = None, count: int = 20) -> List[Dict]: 

    """ 

    Extract hospital details using Gemini with grounding. 

     

    Args: 

        query: Search query for hospitals 

        location: Optional location to search in 

        count: Number of hospitals to request (default 20 per call) 

     

    Returns: 

        List of dictionaries containing hospital details 

    """ 

    # Define the modern Google Search tool 

    google_search_tool = types.Tool( 

        google_search=types.GoogleSearch() 

    ) 

     

    # Build the prompt with explicit JSON format request 

    if location: 

        prompt = f"""Find {count} hospitals in {location}. For each hospital, extract and provide: 

1. Name 

2. Complete address 

3. Contact/Phone number 

4. Email address 

 

Return as many hospitals as possible (up to {count}) as a JSON array where each object has these exact keys: "name", "address", "contact", "email". 

Format: [{{"name": "...", "address": "...", "contact": "...", "email": "..."}}, ...]""" 

    else: 

        prompt = f"""Find {count} hospitals based on: {query}. For each hospital, extract and provide: 

1. Name 

2. Complete address 

3. Contact/Phone number 

4. Email address 

 

Return as many hospitals as possible (up to {count}) as a JSON array where each object has these exact keys: "name", "address", "contact", "email". 

Format: [{{"name": "...", "address": "...", "contact": "...", "email": "..."}}, ...]""" 

     

    try: 

        # Generate content with grounding using the new API 

        response = client.models.generate_content( 

            model='gemini-3-flash-preview', 

            contents=prompt, 

            config=types.GenerateContentConfig( 

                tools=[google_search_tool], 

                temperature=0.7 

            ) 

        ) 

         

        # Parse the response - try to extract JSON first 

        hospitals = [] 

        response_text = response.text 

         

        # Try to extract JSON from response 

        try: 

            # Look for JSON array in the response 

            start_idx = response_text.find('[') 

            end_idx = response_text.rfind(']') + 1 

             

            if start_idx != -1 and end_idx > start_idx: 

                json_str = response_text[start_idx:end_idx] 

                hospitals = json.loads(json_str) 

                # Rename keys to match Excel columns 

                for hospital in hospitals: 

                    hospital['Name'] = hospital.pop('name', '') 

                    hospital['Address'] = hospital.pop('address', '') 

                    hospital['Contact'] = hospital.pop('contact', '') 

                    hospital['Email'] = hospital.pop('email', '') 

            else: 

                # Try to find JSON objects 

                json_pattern = r'\{[^{}]*"name"[^{}]*\}' 

                matches = re.findall(json_pattern, response_text, re.DOTALL) 

                if matches: 

                    hospitals = [json.loads(match) for match in matches] 

                    for hospital in hospitals: 

                        hospital['Name'] = hospital.pop('name', '') 

                        hospital['Address'] = hospital.pop('address', '') 

                        hospital['Contact'] = hospital.pop('contact', '') 

                        hospital['Email'] = hospital.pop('email', '') 

        except json.JSONDecodeError: 

            # Fallback: parse text format 

            lines = response_text.split('\n') 

            current_hospital = {} 

             

            for line in lines: 

                line = line.strip() 

                if not line: 

                    if current_hospital and len(current_hospital) > 0: 

                        hospitals.append(current_hospital) 

                        current_hospital = {} 

                    continue 

                 

                # Try to parse different formats 

                if 'name' in line.lower() and ':' in line: 

                    name = line.split(':', 1)[1].strip() 

                    current_hospital['Name'] = name 

                elif 'address' in line.lower() and ':' in line: 

                    address = line.split(':', 1)[1].strip() 

                    current_hospital['Address'] = address 

                elif ('contact' in line.lower() or 'phone' in line.lower() or 'tel' in line.lower()) and ':' in line: 

                    contact = line.split(':', 1)[1].strip() 

                    current_hospital['Contact'] = contact 

                elif 'email' in line.lower() and ':' in line: 

                    email = line.split(':', 1)[1].strip() 

                    current_hospital['Email'] = email 

             

            if current_hospital and len(current_hospital) > 0: 

                hospitals.append(current_hospital) 

         

        return hospitals 

         

    except Exception as e: 

        print(f"Error extracting hospital details: {str(e)}") 

        return [] 

 

def save_to_excel(hospitals: List[Dict], filename: str = 'hospitals.xlsx'): 

    """ 

    Save hospital details to Excel file. 

     

    Args: 

        hospitals: List of hospital dictionaries 

        filename: Output Excel filename 

    """ 

    if not hospitals: 

        print("No hospital data to save.") 

        return 

    # Ensure all dictionaries have the same keys 

    columns = ['Name', 'Address', 'Contact', 'Email'] 

    for hospital in hospitals: 

        for col in columns: 

            if col not in hospital: 

                hospital[col] = '' 

     

    # Create DataFrame 

    df = pd.DataFrame(hospitals, columns=columns) 

     

    # Save to Excel 

    df.to_excel(filename, index=False, engine='openpyxl') 

    print(f"Saved {len(hospitals)} hospital records to {filename}") 

 

def remove_duplicates(hospitals: List[Dict]) -> List[Dict]: 

    """ 

    Remove duplicate hospitals based on name and address. 

     

    Args: 

        hospitals: List of hospital dictionaries 

     

    Returns: 

        List of unique hospitals 

    """ 

    seen = set() 

    unique_hospitals = [] 

     

    for hospital in hospitals: 

        # Create a unique key from name and address 

        name = str(hospital.get('Name', '')).strip().lower() 

        address = str(hospital.get('Address', '')).strip().lower() 

        key = (name, address) 

         

        if key not in seen and name:  # Only add if name exists 

            seen.add(key) 

            unique_hospitals.append(hospital) 

     

    return unique_hospitals 

 

def main(): 

    """ 

    Main function to extract hospital details and save to Excel. 

    """ 

    target_count = 20 

    location = "Africa" 

    all_hospitals = [] 

     

    # List of African countries/regions to search for comprehensive coverage 

    african_regions = [ 

        "Africa", 

        "South Africa hospitals", 

        "Nigeria hospitals", 

        "Kenya hospitals", 

        "Egypt hospitals", 

        "Ghana hospitals", 

        "Morocco hospitals", 

        "Ethiopia hospitals", 

        "Tanzania hospitals", 

        "Uganda hospitals", 

        "Algeria hospitals", 

        "Sudan hospitals", 

        "Mozambique hospitals", 

        "Angola hospitals", 

        "Ivory Coast hospitals", 

        "Madagascar hospitals", 

        "Cameroon hospitals", 

        "Niger hospitals", 

        "Burkina Faso hospitals", 

        "Mali hospitals", 

        "Malawi hospitals", 

        "Zambia hospitals", 

        "Senegal hospitals", 

        "Chad hospitals"

    ] 

    print(f"Searching for {target_count} hospitals in {location}...") 

    print("Collecting data from multiple regions...\n") 

    hospitals_per_call = 20 

    call_count = 0 

    max_calls = 3  # Limit for collecting 20 hospitals 

     

    # Try to get hospitals from different regions 

    for region in african_regions: 

        if len(all_hospitals) >= target_count: 

            break 

         

        if call_count >= max_calls: 

            print(f"\nReached maximum API calls limit ({max_calls}). Continuing with collected data...") 

            break 

         

        print(f"Searching in: {region}... (Collected: {len(all_hospitals)}/{target_count})") 

         

        try: 

            hospitals = extract_hospital_details("hospitals", region, hospitals_per_call) 

             

            if hospitals: 

                # Remove duplicates before adding 

                unique_new = [] 

                existing_names = {str(h.get('Name', '')).strip().lower() for h in all_hospitals} 

                 

                for h in hospitals: 

                    name = str(h.get('Name', '')).strip().lower() 

                    if name and name not in existing_names: 

                        unique_new.append(h) 

                        existing_names.add(name) 

                 

                all_hospitals.extend(unique_new) 

                print(f"  Found {len(unique_new)} new hospitals (Total: {len(all_hospitals)})") 

             

            call_count += 1 

             # Small delay to avoid rate limiting 

            time.sleep(1)         

        except Exception as e: 

            print(f"  Error searching {region}: {str(e)}") 

            continue 

     

    # Remove any remaining duplicates 

    all_hospitals = remove_duplicates(all_hospitals) 

     

    # Limit to target count 

    if len(all_hospitals) > target_count: 

        all_hospitals = all_hospitals[:target_count] 

     

    if all_hospitals: 

        print(f"\nTotal unique hospitals found: {len(all_hospitals)}") 

        save_to_excel(all_hospitals, '20_africa_hospitals.xlsx') 

    else: 

        print("No hospitals found or extraction failed.") 

 

if name == "__main__": 

    main() 

8. Sample Output (Excel) 

 

 

9. Key Benefits of This Approach 

  • High accuracy for public contact data 

  • Live verification at query time 

  • Reduced hallucination risk 

  • Audit-friendly structured output 

  • No dependency on stored documents or embeddings 

 

10. When to Use Real-Time Search Grounding 

Recommended For: 

  • Public directory validation 

  • Compliance and audit workflows 

  • CRM enrichment 

  • Research and data verification 

Not Ideal For: 

  • Fully offline systems 

  • Static internal documentation 

  • Latency-critical applications 

11. Conclusion 

In modern AI systems, trust and verifiability matter more than raw generation ability. 

Gemini 3’s real-time search grounding provides a practical, production-ready solution for extracting accurate, up-to-date public information without relying on pre-collected datasets. 

This implementation demonstrates how grounded AI can be applied directly to real-world business problems — with outputs that stakeholders can verify, validate, and trust.