Spaces:
Running
Running
fix(NEW-A3 part1): replace em-dashes/smart-quotes in 56+ Python files -- CI requires pure ASCII source
8a0fba4 | import os | |
| from datetime import datetime | |
| from bs4 import BeautifulSoup | |
| from scrapers.base_scraper import BaseScraper | |
| from loguru import logger | |
| class EDScraper(BaseScraper): | |
| BASE_URL = "https://enforcementdirectorate.gov.in" | |
| PRESS_URL = "https://enforcementdirectorate.gov.in/press-release" | |
| STATS_URL = "https://enforcementdirectorate.gov.in/statistics" | |
| def __init__(self): | |
| super().__init__(name="ed", delay=2.0) | |
| self.session.headers.update({ | |
| "User-Agent": ( | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " | |
| "AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36" | |
| ), | |
| }) | |
| def fetch_press_releases(self, limit: int = 20, | |
| save: bool = True) -> list: | |
| logger.info("[ED] Fetching press releases...") | |
| html = self.get_html(self.PRESS_URL) | |
| releases = [] | |
| if html: | |
| releases = self._parse_press_releases(html, limit) | |
| if not releases: | |
| logger.warning("[ED] Could not fetch live data -- using sample") | |
| releases = self._get_sample_releases() | |
| if save and releases: | |
| ts = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| filepath = f"data/samples/ed_releases_{ts}.json" | |
| self.save_json(releases, filepath) | |
| logger.success(f"[ED] Saved {len(releases)} releases") | |
| return releases | |
| def _parse_press_releases(self, html: str, limit: int) -> list: | |
| soup = BeautifulSoup(html, "lxml") | |
| releases = [] | |
| for link in soup.find_all("a", href=True): | |
| title = link.get_text(strip=True) | |
| href = link.get("href", "") | |
| if len(title) < 15: | |
| continue | |
| if not any(k in title.lower() for k in | |
| ["attach","arrest","pmla","fema","crore","case"]): | |
| continue | |
| full_url = (href if href.startswith("http") | |
| else self.BASE_URL + href) | |
| releases.append({ | |
| "title": title, | |
| "url": full_url, | |
| "source": "Enforcement Directorate", | |
| "source_url": self.BASE_URL, | |
| "scraped_at": datetime.now().isoformat(), | |
| "entity_type": "ed_press_release", | |
| }) | |
| if len(releases) >= limit: | |
| break | |
| logger.info(f"[ED] Parsed {len(releases)} press releases") | |
| return releases | |
| def _get_sample_releases(self) -> list: | |
| return [ | |
| { | |
| "title": ( | |
| "ED Attaches Properties Worth Rs 10021.46 Crore " | |
| "in PACL Money Laundering Case" | |
| ), | |
| "date": "2026-02-18", | |
| "amount_crore":10021.46, | |
| "case_type": "PMLA", | |
| "accused": "PACL India Limited", | |
| "url": ( | |
| "https://enforcementdirectorate.gov.in/" | |
| "press-release/2026/feb/pacl" | |
| ), | |
| "source": "Enforcement Directorate (sample)", | |
| "source_url": self.BASE_URL, | |
| "scraped_at": datetime.now().isoformat(), | |
| "entity_type": "ed_press_release", | |
| }, | |
| ] | |
| if __name__ == "__main__": | |
| print("=" * 55) | |
| print("BharatGraph - ED Scraper") | |
| print("=" * 55) | |
| scraper = EDScraper() | |
| releases = scraper.fetch_press_releases(save=True) | |
| print(f"\n Records: {len(releases)}") | |
| if releases: | |
| print(f" Example: {releases[0]['title'][:60]}") | |
| print("\nDone!") | |