Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| sidebar_position: 8 | |
| # Loading Meeting Data for Priority States | |
| Guide to loading existing LocalView meeting data and updating with recent scraping for AL, GA, IN, MA, WA, WI. | |
| ## π Current Meeting Data Status | |
| ### What You Have Now | |
| **OpenStates Legislative Events** (Already loaded): | |
| - Alabama (AL): Legislative committee hearings | |
| - Georgia (GA): Legislative events | |
| - Indiana (IN): Legislative events | |
| - Massachusetts (MA): Legislative events | |
| - Washington (WA): Legislative events | |
| - Wisconsin (WI): Legislative events | |
| **Location**: `data/gold/states/{STATE}/events_events.parquet` | |
| **What's Missing**: Municipal/local government meetings (city council, county boards, school boards) | |
| ## π― Three-Step Process | |
| ### Step 1: Check What LocalView Data Exists | |
| LocalView is a Harvard dataset with 153K+ municipal meeting transcripts from YouTube. | |
| ```bash | |
| # Check if you have LocalView data downloaded | |
| ls -lh data/cache/localview/ | |
| # If you only see municipality_channels.csv with demo data, | |
| # you need to download the actual LocalView dataset | |
| ``` | |
| ### Step 2: Download LocalView Dataset (Optional) | |
| If you want the full historical dataset (2006-2023): | |
| **Manual Download from Harvard Dataverse:** | |
| 1. Visit: https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/NJTBEM | |
| 2. Download these files to `data/cache/localview/`: | |
| - `municipalities.csv` (list of 1000+ jurisdictions) | |
| - `meetings.csv` (153K meeting metadata) | |
| - `transcripts.csv` (video transcripts with captions) | |
| 3. Run ingestion script: | |
| ```bash | |
| python scripts/datasources/localview/localview_ingestion.py | |
| ``` | |
| **What This Gives You:** | |
| - 153,452 meeting transcripts (2006-2023) | |
| - 1,000+ municipalities across all states | |
| - Full text search of meeting discussions | |
| - Speaker identification and attendance tracking | |
| ### Step 3: Scrape Recent Meetings (2024-2026) | |
| The LocalView dataset ends in 2023. To get 2024-2026 data, scrape YouTube directly. | |
| #### A. Find Municipal YouTube Channels | |
| First, you need to discover YouTube channels for municipalities in your 6 states. | |
| **Option 1: Use Discovery Scripts** | |
| ```bash | |
| # Discover government URLs for priority states | |
| python scripts/discovery/discover_jurisdictions.py \ | |
| --states AL,GA,IN,MA,WA,WI \ | |
| --types city,county \ | |
| --output data/discovered_urls.json | |
| # Extract YouTube channels from discovered sites | |
| python scripts/localview/update_municipality_list.py \ | |
| --states AL,GA,IN,MA,WA,WI | |
| ``` | |
| **Option 2: Manual Research** | |
| For major cities in each state: | |
| 1. Go to city's official website | |
| 2. Look for "Meetings", "City Council", "Agendas" | |
| 3. Check if they have YouTube channel link | |
| 4. Add to `data/cache/localview/municipality_channels.csv` | |
| Example format: | |
| ```csv | |
| municipality,channel_id,state,population,added_date | |
| Birmingham AL,UCxxxxxxxxxxxxxxxxxx,AL,200000,2026-05-03 | |
| Atlanta GA,UCyyyyyyyyyyyyyyyyyy,GA,500000,2026-05-03 | |
| Indianapolis IN,UCzzzzzzzzzzzzzzzzzz,IN,880000,2026-05-03 | |
| ``` | |
| #### B. Run YouTube Scraper | |
| **Setup:** | |
| ```bash | |
| # Get YouTube API key from Google Cloud Console | |
| # https://console.cloud.google.com/apis/credentials | |
| # Add to .env | |
| echo "YOUTUBE_API_KEY=your_key_here" >> .env | |
| ``` | |
| **Scrape by State:** | |
| ```bash | |
| # Scrape all 6 priority states | |
| python scripts/localview/scrape_youtube_channels.py \ | |
| --states AL,GA,IN,MA,WA,WI \ | |
| --since 2024-01-01 | |
| # Or scrape specific channels | |
| python scripts/localview/scrape_youtube_channels.py \ | |
| --channels "UCxxxxx,UCyyyyy" \ | |
| --max-videos 100 | |
| ``` | |
| **What This Does:** | |
| 1. Gets recent videos from municipal YouTube channels | |
| 2. Downloads auto-generated captions/transcripts | |
| 3. Extracts meeting metadata (date, title, description) | |
| 4. Saves to `data/cache/localview/videos_{STATE}_{date}.parquet` | |
| #### C. Process Transcripts | |
| Extract speaker names and meeting details: | |
| ```bash | |
| # Extract transcripts from videos | |
| python scripts/localview/extract_transcripts.py \ | |
| --states AL,GA,IN,MA,WA,WI \ | |
| --output data/gold/meetings/ | |
| # Extract contact information from transcripts | |
| python scripts/manage_contacts.py extract \ | |
| --states AL,GA,IN,MA,WA,WI \ | |
| --batch-size 1000 | |
| ``` | |
| ## π Final Data Structure | |
| After completing all steps: | |
| ``` | |
| data/gold/ | |
| βββ states/ | |
| β βββ AL/ | |
| β β βββ events_events.parquet # OpenStates legislative events | |
| β β βββ events_participants.parquet | |
| β β βββ meetings_local.parquet # LocalView municipal meetings | |
| β β βββ contact_official.parquet # Legislators + local officials | |
| β βββ GA/ | |
| β β βββ events_events.parquet | |
| β β βββ meetings_local.parquet | |
| β β βββ contact_official.parquet | |
| β βββ ... (IN, MA, WA, WI) | |
| β | |
| βββ meetings/ # Cross-state meeting data | |
| βββ meetings_transcripts.parquet # All 153K transcripts | |
| βββ contacts_local_officials.parquet # Aggregated local officials | |
| βββ contacts_meeting_attendance.parquet # Attendance records | |
| ``` | |
| ## π Querying Meeting Data | |
| ### Find Meetings by State | |
| ```python | |
| import polars as pl | |
| # Load Alabama meetings | |
| al_meetings = pl.read_parquet('data/gold/states/AL/meetings_local.parquet') | |
| # Filter by date range | |
| recent = al_meetings.filter( | |
| pl.col('meeting_date') >= '2024-01-01' | |
| ) | |
| print(f"Found {len(recent)} Alabama meetings since 2024") | |
| ``` | |
| ### Search Meeting Transcripts | |
| ```python | |
| # Load all transcripts | |
| transcripts = pl.read_parquet('data/gold/meetings/meetings_transcripts.parquet') | |
| # Search for oral health mentions | |
| oral_health = transcripts.filter( | |
| pl.col('caption_text').str.contains('(?i)dental|teeth|oral health|fluoride') | |
| ) | |
| # Group by state | |
| by_state = oral_health.group_by('state').count() | |
| print(by_state) | |
| ``` | |
| ### Find Officials Attending Meetings | |
| ```python | |
| # Load attendance records | |
| attendance = pl.read_parquet('data/gold/meetings/contacts_meeting_attendance.parquet') | |
| # Find all meetings for a specific official | |
| officials_meetings = attendance.filter( | |
| pl.col('name') == 'Stephanie Briggs' | |
| ) | |
| print(f"Stephanie Briggs attended {len(officials_meetings)} meetings") | |
| ``` | |
| ## π Quick Start for Development | |
| If you just want to test with sample data: | |
| ```bash | |
| # 1. Use existing OpenStates events (already loaded) | |
| python -c " | |
| import polars as pl | |
| df = pl.read_parquet('data/gold/states/AL/events_events.parquet') | |
| print(f'Alabama legislative events: {len(df)}') | |
| print(df.head()) | |
| " | |
| # 2. Scrape a single city for testing | |
| python scripts/localview/scrape_youtube_channels.py \ | |
| --channels "UCMFAKdxL6sATpkRqLdJyKUg" \ | |
| --max-videos 10 | |
| # 3. Process and view results | |
| python scripts/localview/extract_transcripts.py --latest | |
| ``` | |
| ## π Related Documentation | |
| - [LocalView Integration Guide](../../docs/LOCALVIEW_INTEGRATION_GUIDE.md) | |
| - [Contacts & Meetings Workflow](../../docs/CONTACTS_MEETINGS_WORKFLOW.md) | |
| - [Data Sources](../../docs/DATA_SOURCES.md) | |
| ## β οΈ Important Notes | |
| ### API Quotas | |
| YouTube API has daily quotas: | |
| - **10,000 units/day** (free tier) | |
| - Fetching 1 video = ~3 units | |
| - Can scrape ~3,000 videos/day | |
| **Strategy**: Prioritize high-population cities, scrape incrementally | |
| ### Storage Requirements | |
| - Full LocalView dataset: ~3 GB compressed | |
| - Transcripts with embeddings: ~10 GB | |
| - Videos (if downloading): ~500 GB (not recommended) | |
| **Recommendation**: Store transcripts only, not videos | |
| ### Data Freshness | |
| - OpenStates: Updated weekly (legislative sessions) | |
| - YouTube scraping: Run weekly/monthly for new meetings | |
| - LocalView dataset: Historical data only (2006-2023) | |
| ## π Troubleshooting | |
| ### "YOUTUBE_API_KEY not found" | |
| ```bash | |
| # Get API key from Google Cloud Console | |
| # Enable YouTube Data API v3 | |
| # Create credentials -> API Key | |
| echo "YOUTUBE_API_KEY=your_key_here" >> .env | |
| ``` | |
| ### "No videos found for channel" | |
| - Verify channel ID is correct (starts with "UC") | |
| - Check channel has public videos | |
| - Ensure videos have captions enabled | |
| ### "Transcript not available" | |
| - Only videos with auto-captions or manual captions work | |
| - Some cities disable captions (can't extract text) | |
| - Fallback: Use video metadata (title, description) | |
| ### "Out of API quota" | |
| ```bash | |
| # Check quota usage at: | |
| # https://console.cloud.google.com/apis/api/youtube.googleapis.com/quotas | |
| # Solutions: | |
| # 1. Wait 24 hours for reset | |
| # 2. Request quota increase | |
| # 3. Use multiple API keys (rotate daily) | |
| ``` | |