Scrapes EC MDCG guidance page to detect new/updated MDCG documents.
| 1053 | # --------------------------------------------------------------------------- |
| 1054 | |
| 1055 | class MDCGPageChecker: |
| 1056 | """Scrapes EC MDCG guidance page to detect new/updated MDCG documents.""" |
| 1057 | |
| 1058 | MDCG_URL = ( |
| 1059 | "https://health.ec.europa.eu/medical-devices-sector/" |
| 1060 | "new-regulations/guidance-mdcg-endorsed-documents-and-other-guidance_en" |
| 1061 | ) |
| 1062 | |
| 1063 | # Matches patterns like: MDCG 2021-24, MDCG 2024-13, MDCG 2022-5 rev.1 |
| 1064 | _REF_RE = re.compile( |
| 1065 | r"MDCG\s+(\d{4})[-–](\d+)(?:[-/](\d+))?" |
| 1066 | r"(?:\s*(?:rev\.?\s*(\d+)|v(\d+)|ADD\.?\s*(\d+)))?", |
| 1067 | re.IGNORECASE, |
| 1068 | ) |
| 1069 | _DATE_RE = re.compile( |
| 1070 | r"(January|February|March|April|May|June|July|August|September|" |
| 1071 | r"October|November|December)\s+(\d{4})" |
| 1072 | ) |
| 1073 | _MONTHS = { |
| 1074 | "january": "01", "february": "02", "march": "03", "april": "04", |
| 1075 | "may": "05", "june": "06", "july": "07", "august": "08", |
| 1076 | "september": "09", "october": "10", "november": "11", "december": "12", |
| 1077 | } |
| 1078 | |
| 1079 | def __init__(self, session: requests.Session, state: dict, db_comparator): |
| 1080 | self.session = session |
| 1081 | self.state = state |
| 1082 | self.db_comparator = db_comparator |
| 1083 | |
| 1084 | def check(self, source_id: str, source: dict) -> Optional[dict]: |
| 1085 | """Fetch EC page, parse all MDCG refs, compare with DB.""" |
| 1086 | try: |
| 1087 | resp = self.session.get(self.MDCG_URL, timeout=30) |
| 1088 | resp.raise_for_status() |
| 1089 | except Exception as e: |
| 1090 | print(f" ERROR fetching EC MDCG page: {e}") |
| 1091 | return None |
| 1092 | |
| 1093 | page_text = resp.text |
| 1094 | official_docs = self._parse_mdcg_refs(page_text) |
| 1095 | if not official_docs: |
| 1096 | print(f" WARNING: No MDCG refs parsed from EC page") |
| 1097 | return None |
| 1098 | |
| 1099 | print(f" INFO: Parsed {len(official_docs)} unique MDCG documents from EC page") |
| 1100 | |
| 1101 | new_items = [] |
| 1102 | update_items = [] |
| 1103 | |
| 1104 | for doc_id, info in official_docs.items(): |
| 1105 | classification, desc = self.db_comparator.classify( |
| 1106 | "eu_mdr/mdcg", info["title"], info.get("url", ""), info.get("date", "") |
| 1107 | ) |
| 1108 | if classification == "new": |
| 1109 | new_items.append({ |
| 1110 | "title": info["title"], |
| 1111 | "link": info.get("url", ""), |
| 1112 | "pub_date": info.get("date", ""), |