소스 정보
- 저장소
- JohnNuwan/EVA_CORE
- 최근 소스 활동
- 2026년 7월 18일 08:30
- 감지된 SKILL.md 언어
- 프랑스어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill siemens-audit명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Concevoir et maintenir un watchdog auto-correcteur pour services HTTP — checks de santé, auto-restart, état persistant, rapports et pièges bash.
Serveur de messagerie sécurisé auto-hébergé (Signal-like) avec Flask + WebSocket + AES-256-GCM + pont EVA
ADAM-SENTINEL — Veilleur technologique 24h/24h. Scanne 10 domaines, cree des rapports, met a jour les skills, alerte sur les CVE et breaking changes.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | siemens-audit |
| description | Extraire des données d'audit Siemens à partir de PDF. |
| version | 2.0.0 |
| author | EVA |
| license | Privée EVA St-Étienne |
| platforms | ["linux","macos","windows"] |
| metadata | {"EVA":{"tags":["industrial-automation","siemens","audit","pdf-parsing","data-extraction","python","pypdf","eph","external-exchanges","ids"],"related_skills":["industrial-documents","automation-linter","plc-diagnostic"]}} |
Cette compétence guide l'extraction structurée de données depuis des documents d'audit industriels Siemens (généralement au format PDF) vers un format texte standardisé. Elle cible spécifiquement deux sections critiques des rapports d'audit :
Ces documents d'audit sont produits par les outils Siemens (ex: SIMATIC IDS, Industrial Cyber Security Assessment) et servent à cartographier les flux de données et les communications entre systèmes d'automatisation.
Les fichiers PDF d'audit posent plusieurs défis d'extraction :
Pour surmonter ces limitations, cette compétence utilise la bibliothèque pypdf sous Python.
À utiliser lorsque l'utilisateur demande :
client_data/EPH/).plc-diagnostic).pypdfimport pypdf
import re
from pathlib import Path
def extract_text_from_pdf(pdf_path: str) -> str:
"""Extrait le texte brut de toutes les pages d'un fichier PDF.
Args:
pdf_path: Chemin absolu ou relatif vers le fichier PDF.
Returns:
str: Texte concaténé de toutes les pages, avec séparateurs de pages.
"""
reader = pypdf.PdfReader(pdf_path)
pages_text = []
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text and text.strip():
# Nettoyage des espaces multiples
text = re.sub(r'\s+', ' ', text)
pages_text.append(f"--- PAGE {i+1} ---\n{text}")
return "\n".join(pages_text)
def extract_sections(text: str) -> dict:
"""Détecte et sépare les sections 1.5 et 2.5 du texte extrait.
Args:
text: Texte brut extrait du PDF.
Returns:
dict: Dictionnaire avec les clés 'section_1_5', 'section_2_5', 'other'.
"""
sections = {'section_1_5': '', 'section_2_5': '', 'other': ''}
# Patterns de détection des sections
patterns = {
'section_1_5': r'(?i)(?:section\s*1\.5|1\.5\s+EPH-EM|EPH[-\s]EM\s+Communications)',
'section_2_5': r'(?i)(?:section\s*2\.5|2\.5\s+External\s+Exchanges|External\s+Exchanges)',
}
# Logique de découpage par sections
# (implémentation adaptée au format réel des documents)
for key, pattern in patterns.items():
match = re.search(pattern, text)
if match:
start = match.start()
# Chercher la section suivante pour la fin
next_section = None
for other_key, other_pattern in patterns.items():
if other_key != key:
other_match = re.search(other_pattern, text[start + len(match.group()):])
if other_match:
next_section = start + len(match.group()) + other_match.start()
break
sections[key] = text[start:next_section] if next_section else text[start:]
sections
Cette section répertorie les échanges de signaux externes, en particulier de type « eph to / from eph ».
'eph to / from eph'.610C5_P_PCIP_BTL_2).E56_90_IDS851_An3_V00). Tronquer tout titre supplémentaire ou extension (.md, .pdf).FILENAME: [Nom propre nettoyé]
INSTANCE_SOURCE: [Titre exact du document]
- Instance_Target: [Vrai nom cible trouvé]
- Type: eph to / from eph
def extract_external_exchanges(text: str, filename: str) -> list[dict]:
"""Extrait les échanges externes (Section 2.5) du texte PDF.
Args:
text: Texte de la Section 2.5.
filename: Nom du fichier source nettoyé.
Returns:
list[dict]: Liste des échanges externes extraits.
"""
exchanges = []
lines = text.split('\n')
# Nettoyage du nom de fichier
clean_filename = re.sub(r'\s*[-–—].*$', '', filename)
clean_filename = re.sub(r'\.(pdf|md)$', '', clean_filename).strip()
# Recherche du titre du document (généralement en haut de section)
doc_title = ""
for line in lines[:20]:
if 'INSTANCE' in line.upper() or 'DOCUMENT' in line.upper():
doc_title = line.strip()
break
# Parsing du tableau des échanges
current_table = False
for i, line in enumerate(lines):
# Détection d'une ligne de tableau significative
if re.search(r'eph\s+to\s+/\s+from\s+eph', line, re.IGNORECASE):
# Extraction des instances
parts = line.split('|')
if len(parts) >= 2:
source = parts[0].strip()
target = parts[1].strip()
target.lower():
target = resolve_note(target, lines[i:i+])
target target.upper() != :
exchanges.append({
: clean_filename,
: doc_title clean_filename,
: target,
:
})
exchanges
() -> :
line context_lines:
= re.search(, line)
:
.group()
note_ref
Cette section détaille les communications internes entre les équipements EPH (Electrical Power & Hydraulic) et EM (Equipment Module).
664C6_E_B_INLET ou 664C6_E_B_Outlet).E56_90_IDSxxx_Anxx_Vxx). Supprimer tout texte après un tiret - et les extensions de fichier.*) dans la colonne « EMT » ET une valeur valide dans « Instance Tag ».EPH-EM.FILENAME: [Préfixe propre nettoyé]
INSTANCE_SOURCE: [Titre exact du document]
- Instance_Target: [Target Instance trouvé dans Instance Tag]
- Type: EPH-EM
FILENAME: E56_90_IDS851_An3_V00
INSTANCE_SOURCE: E56_90 - System Overview IDS851_An3_V00
- Instance_Target: 664C6_E_B_INLET
- Type: EPH-EM
FILENAME: E56_90_IDS851_An3_V00
INSTANCE_SOURCE: E56_90 - System Overview IDS851_An3_V00
- Instance_Target: 664C6_E_B_OUTLET
- Type: EPH-EM
Ignorer les notes en bas de tableau :
"See note below" comme cible d'instance dans le résultat final.[0-9A-Z_]+ après la note.Garder des extensions ou des titres dans FILENAME :
FILENAME: E56_90_IDS851_An3_V00 - MBR.pdf-, —, ou –. Supprimer .pdf, .md. Résultat attendu : FILENAME: E56_90_IDS851_An3_V00.Confusion entre le type d'échange :
Type: eph to / from ephType: EPH-EMOCR imparfaite sur les PDF scannés :
Erreur : Les PDF scannés (non natifs) produisent du texte avec des caractères mal reconnus, rendant les motifs regex inefficaces.
Correction : Vérifier la qualité du texte extrait. Si le texte contient trop d'artefacts, suggérer d'utiliser un OCR (Tesseract) en amont :
# Détection de qualité OCR
def is_text_quality_acceptable(text: str) -> bool:
"""Vérifie si le texte extrait est exploitable (>70% de mots valides)."""
words = text.split()
valid = sum(1 for w in words if re.match(r'^[A-Za-z0-9_\-\.]+$', w))
(words) > (valid / (words)) >
pypdf installée dans le .venv du projet.pdfplumber est installé pour les tableaux complexes avec cellules fusionnées..pdf, .md et des textes après tiret).* dans la colonne EMT.Tableaux avec cellules fusionnées :
Erreur : pypdf extrait les cellules fusionnées comme du texte plat, perdant la structure ligne/colonne.
Correction : Utiliser pdfplumber en complément pour les tableaux complexes :
pip install pdfplumber
import pdfplumber
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for table in tables:
for row in table:
print(row)