mirror of
https://forge.chapril.org/tykayn/orgmode-to-gemini-blog
synced 2025-06-20 09:04:42 +02:00
174 lines
No EOL
6.8 KiB
Python
174 lines
No EOL
6.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Scanne les fichiers Org d'un dossier pour répertorier les liens.
|
|
Génère un JSON listant pour chaque article ses liens et statistiques par domaine.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import json
|
|
import argparse
|
|
import urllib.parse
|
|
from datetime import datetime
|
|
from collections import Counter, defaultdict
|
|
|
|
def extract_links_from_org(file_path):
|
|
"""Extrait tous les liens d'un fichier Org"""
|
|
links = []
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as file:
|
|
content = file.read()
|
|
|
|
# Pattern pour trouver les liens Org-mode: [[url][description]] ou [[url]]
|
|
pattern = r'\[\[((?:https?:\/\/|www\.)[^\]]+)\](?:\[([^\]]*)\])?'
|
|
matches = re.finditer(pattern, content)
|
|
|
|
for match in matches:
|
|
url = match.group(1)
|
|
description = match.group(2) if match.group(2) else ""
|
|
links.append({"url": url, "description": description})
|
|
|
|
# Chercher aussi les liens simples http:// ou https:// qui ne sont pas dans la syntaxe [[]]
|
|
simple_pattern = r'(?<!\[)(?:https?:\/\/)[^\s\]]+(?!\])'
|
|
simple_matches = re.finditer(simple_pattern, content)
|
|
|
|
for match in simple_matches:
|
|
url = match.group(0)
|
|
links.append({"url": url, "description": ""})
|
|
|
|
except Exception as e:
|
|
print(f"Erreur lors de la lecture de {file_path}: {e}")
|
|
|
|
return links
|
|
|
|
def extract_domain(url):
|
|
"""Extrait le nom de domaine d'une URL"""
|
|
try:
|
|
parsed_url = urllib.parse.urlparse(url)
|
|
domain = parsed_url.netloc
|
|
|
|
# Supprimer www. si présent
|
|
if domain.startswith('www.'):
|
|
domain = domain[4:]
|
|
|
|
return domain
|
|
except Exception:
|
|
return url
|
|
|
|
def scan_directory(directory):
|
|
"""Scanne un répertoire et ses sous-répertoires pour trouver des fichiers Org"""
|
|
article_links = {}
|
|
domain_counter = Counter()
|
|
|
|
# Parcourir tous les sous-dossiers
|
|
for root, _, files in os.walk(directory):
|
|
for file in files:
|
|
if file.endswith('.org'):
|
|
file_path = os.path.join(root, file)
|
|
file_links = extract_links_from_org(file_path)
|
|
|
|
if file_links:
|
|
relative_path = os.path.relpath(file_path, os.path.dirname(directory))
|
|
article_links[relative_path] = file_links
|
|
|
|
# Compter les domaines
|
|
for link in file_links:
|
|
domain = extract_domain(link["url"])
|
|
if domain:
|
|
domain_counter[domain] += 1
|
|
|
|
print(f"Trouvé {len(file_links)} liens dans {relative_path}")
|
|
|
|
return article_links, domain_counter
|
|
|
|
def merge_scan_results(results1, results2):
|
|
"""Combine les résultats de deux scans"""
|
|
merged_article_links = {**results1[0], **results2[0]}
|
|
merged_domain_counter = results1[1] + results2[1]
|
|
return merged_article_links, merged_domain_counter
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Scanner les liens dans les fichiers Org")
|
|
parser.add_argument("source_dir", help="Dossier source contenant les fichiers Org")
|
|
parser.add_argument("--output", default="links_report.json",
|
|
help="Fichier JSON de sortie (défaut: links_report.json)")
|
|
args = parser.parse_args()
|
|
|
|
# Construire le nom du fichier de sortie avec le nom du dossier source
|
|
if args.output == "links_report.json":
|
|
args.output = f"links_report_{args.source_dir}.json"
|
|
|
|
folder_fr = f'sources/{args.source_dir}/lang_fr'
|
|
folder_en = f'sources/{args.source_dir}/lang_en'
|
|
|
|
if not os.path.exists(folder_fr) and not os.path.exists(folder_en):
|
|
print(f"Les dossiers {folder_fr} et {folder_en} n'existent pas.")
|
|
return
|
|
|
|
# Initialiser des résultats vides
|
|
combined_article_links = {}
|
|
combined_domain_counter = Counter()
|
|
|
|
# Scanner le dossier français s'il existe
|
|
if os.path.exists(folder_fr):
|
|
print(f"Scan des liens dans {folder_fr}...")
|
|
fr_results = scan_directory(folder_fr)
|
|
combined_article_links, combined_domain_counter = fr_results
|
|
|
|
print(f"Trouvé {len(combined_article_links)} articles en français avec {sum(len(links) for links in combined_article_links.values())} liens")
|
|
|
|
# Scanner le dossier anglais s'il existe
|
|
if os.path.exists(folder_en):
|
|
print(f"Scan des liens dans {folder_en}...")
|
|
en_results = scan_directory(folder_en)
|
|
|
|
# Si nous avons déjà des résultats en français, les combiner
|
|
if combined_article_links:
|
|
combined_article_links, combined_domain_counter = merge_scan_results(
|
|
(combined_article_links, combined_domain_counter),
|
|
en_results
|
|
)
|
|
else:
|
|
# Sinon, utiliser directement les résultats anglais
|
|
combined_article_links, combined_domain_counter = en_results
|
|
|
|
print(f"Total cumulé: {len(combined_article_links)} articles avec {sum(len(links) for links in combined_article_links.values())} liens")
|
|
|
|
# Préparer les données pour le JSON
|
|
output_data = {
|
|
"meta": {
|
|
"generated_at": datetime.now().isoformat(),
|
|
"source_directory": args.source_dir,
|
|
"total_articles": len(combined_article_links),
|
|
"total_links": sum(len(links) for links in combined_article_links.values()),
|
|
"total_domains": len(combined_domain_counter)
|
|
},
|
|
"article_links": combined_article_links,
|
|
"domains": {
|
|
domain: count for domain, count in sorted(
|
|
combined_domain_counter.items(), key=lambda x: x[1], reverse=True
|
|
)
|
|
}
|
|
}
|
|
|
|
# Créer le dossier de sortie si nécessaire
|
|
output_dir = os.path.dirname(args.output)
|
|
if output_dir and not os.path.exists(output_dir):
|
|
os.makedirs(output_dir)
|
|
|
|
# Sauvegarder les données dans un fichier JSON
|
|
with open(args.output, 'w', encoding='utf-8') as f:
|
|
json.dump(output_data, f, ensure_ascii=False, indent=2)
|
|
|
|
print(f"Rapport généré avec succès dans {args.output}")
|
|
print(f"Total articles: {len(combined_article_links)}")
|
|
print(f"Total liens: {sum(len(links) for links in combined_article_links.values())}")
|
|
print(f"Total domaines: {len(combined_domain_counter)}")
|
|
|
|
# Afficher les 10 domaines les plus fréquents
|
|
print("\nTop 10 des domaines les plus fréquents:")
|
|
for domain, count in list(combined_domain_counter.most_common(10)):
|
|
print(f" {domain}: {count} liens")
|
|
|
|
if __name__ == "__main__":
|
|
main() |