Download index.html from Wizeo/test: direct link, hf CLI and curl.
- Browser
- Download file 22.2 kB
-
https://huggingface.co/spaces/Wizeo/test/resolve/main/index.html
- Command line
-
hf download hf://spaces/Wizeo/test/index.html
-
curl -L -o index.html https://huggingface.co/spaces/Wizeo/test/resolve/main/index.html
22.2 kB
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>LinkedIn Profile Scraper</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .video-preview { | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
| border: 2px dashed #0077b5; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| .btn-primary { | |
| background-color: #0077b5; | |
| transition: all 0.3s ease; | |
| } | |
| .btn-primary:hover { | |
| background-color: #005582; | |
| transform: translateY(-2px); | |
| } | |
| .input-field:focus { | |
| border-color: #0077b5; | |
| box-shadow: 0 0 0 3px rgba(0, 119, 181, 0.2); | |
| } | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| 100% { transform: scale(1); } | |
| } | |
| .pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| #fakeVideo { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| display: none; | |
| } | |
| .video-placeholder { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| height: 100%; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> | |
| <header class="mb-10 text-center"> | |
| <h1 class="text-4xl font-bold text-gray-800 mb-2"> | |
| <i class="fab fa-linkedin text-blue-600 mr-2"></i> LinkedIn Profile Scraper | |
| </h1> | |
| <p class="text-gray-600">Automatisez les visites de profils et capturez des enregistrements vidéo</p> | |
| </header> | |
| <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8"> | |
| <div class="p-6"> | |
| <div class="flex flex-col md:flex-row gap-6"> | |
| <!-- Section Connexion --> | |
| <div class="w-full md:w-1/2"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-sign-in-alt mr-2 text-blue-500"></i> Connexion LinkedIn | |
| </h2> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-gray-700 mb-2">Email</label> | |
| <input type="email" id="email" class="w-full px-4 py-2 rounded-lg border input-field focus:outline-none" placeholder="votre@email.com"> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2">Mot de passe</label> | |
| <input type="password" id="password" class="w-full px-4 py-2 rounded-lg border input-field focus:outline-none" placeholder="••••••••"> | |
| </div> | |
| <button id="loginBtn" class="w-full btn-primary text-white py-3 rounded-lg font-medium flex items-center justify-center"> | |
| <i class="fas fa-lock-open mr-2"></i> Se connecter à LinkedIn | |
| </button> | |
| <div class="text-center text-sm text-gray-500"> | |
| <p>Nous ne stockons pas vos identifiants</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section Profil --> | |
| <div class="w-full md:w-1/2"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-user-circle mr-2 text-blue-500"></i> Paramètres du profil | |
| </h2> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-gray-700 mb-2">URL du profil</label> | |
| <input type="url" id="profileUrl" class="w-full px-4 py-2 rounded-lg border input-field focus:outline-none" placeholder="https://linkedin.com/in/nomdutilisateur"> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 mb-2">Durée d'enregistrement</label> | |
| <select id="duration" class="w-full px-4 py-2 rounded-lg border input-field focus:outline-none"> | |
| <option value="5" selected>5 secondes</option> | |
| <option value="10">10 secondes</option> | |
| <option value="15">15 secondes</option> | |
| </select> | |
| </div> | |
| <button id="startBtn" class="w-full btn-primary text-white py-3 rounded-lg font-medium flex items-center justify-center opacity-50 cursor-not-allowed" disabled> | |
| <i class="fas fa-play mr-2"></i> Démarrer l'enregistrement | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section État --> | |
| <div id="statusSection" class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 hidden"> | |
| <div class="p-6"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-tasks mr-2 text-blue-500"></i> État de l'opération | |
| </h2> | |
| <div class="space-y-6"> | |
| <div> | |
| <div class="flex justify-between mb-1"> | |
| <span class="text-gray-700">Progression</span> | |
| <span id="progressPercent" class="text-gray-700">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="progressBar" class="bg-blue-600 h-2.5 rounded-full progress-bar" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <div id="statusMessages" class="space-y-2"> | |
| <div class="flex items-start text-green-600"> | |
| <i class="fas fa-check-circle mt-1 mr-2"></i> | |
| <span>Connecté avec succès à LinkedIn</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section Aperçu --> | |
| <div id="previewSection" class="bg-white rounded-xl shadow-lg overflow-hidden hidden"> | |
| <div class="p-6"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-video mr-2 text-blue-500"></i> Aperçu de la vidéo | |
| </h2> | |
| <div class="video-preview rounded-lg p-4 mb-4 flex flex-col items-center justify-center h-64"> | |
| <div class="video-placeholder"> | |
| <i class="fas fa-video text-4xl text-gray-400 mb-3"></i> | |
| <p class="text-gray-500 text-center">Votre enregistrement apparaîtra ici</p> | |
| </div> | |
| <video id="fakeVideo" controls> | |
| <source src="" type="video/mp4"> | |
| Votre navigateur ne supporte pas la vidéo. | |
| </video> | |
| </div> | |
| <div class="flex justify-between"> | |
| <button id="downloadBtn" class="btn-primary text-white px-6 py-2 rounded-lg font-medium flex items-center"> | |
| <i class="fas fa-download mr-2"></i> Télécharger | |
| </button> | |
| <button id="newRecordingBtn" class="bg-gray-200 text-gray-800 px-6 py-2 rounded-lg font-medium flex items-center"> | |
| <i class="fas fa-redo mr-2"></i> Nouvel enregistrement | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Instructions --> | |
| <div class="bg-blue-50 rounded-xl p-6 mt-8 border border-blue-100"> | |
| <h3 class="text-lg font-semibold text-blue-800 mb-3 flex items-center"> | |
| <i class="fas fa-info-circle mr-2"></i> Comment ça marche | |
| </h3> | |
| <ol class="list-decimal list-inside space-y-2 text-blue-900"> | |
| <li>Entrez vos identifiants LinkedIn (non stockés)</li> | |
| <li>Collez l'URL du profil que vous souhaitez visiter</li> | |
| <li>Cliquez sur "Démarrer l'enregistrement"</li> | |
| <li>L'outil va automatiquement défiler et enregistrer pendant 5 secondes</li> | |
| <li>Téléchargez votre enregistrement vidéo</li> | |
| </ol> | |
| <div class="mt-4 p-3 bg-blue-100 rounded-lg text-blue-800 flex items-start"> | |
| <i class="fas fa-exclamation-triangle mt-1 mr-2"></i> | |
| <span>Note : Ceci est une démonstration frontend. Une automatisation réelle de LinkedIn nécessiterait des services backend en raison des restrictions de sécurité des navigateurs.</span> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Éléments | |
| const emailInput = document.getElementById('email'); | |
| const passwordInput = document.getElementById('password'); | |
| const loginBtn = document.getElementById('loginBtn'); | |
| const profileUrlInput = document.getElementById('profileUrl'); | |
| const startBtn = document.getElementById('startBtn'); | |
| const statusSection = document.getElementById('statusSection'); | |
| const previewSection = document.getElementById('previewSection'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const progressPercent = document.getElementById('progressPercent'); | |
| const statusMessages = document.getElementById('statusMessages'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const newRecordingBtn = document.getElementById('newRecordingBtn'); | |
| const fakeVideo = document.getElementById('fakeVideo'); | |
| const videoPlaceholder = document.querySelector('.video-placeholder'); | |
| const durationSelect = document.getElementById('duration'); | |
| // Activer le bouton de démarrage quand l'URL est entrée | |
| profileUrlInput.addEventListener('input', function() { | |
| if (profileUrlInput.value.trim() !== '') { | |
| startBtn.classList.remove('opacity-50', 'cursor-not-allowed'); | |
| startBtn.disabled = false; | |
| } else { | |
| startBtn.classList.add('opacity-50', 'cursor-not-allowed'); | |
| startBtn.disabled = true; | |
| } | |
| }); | |
| // Bouton de connexion | |
| loginBtn.addEventListener('click', function() { | |
| const email = emailInput.value.trim(); | |
| const password = passwordInput.value.trim(); | |
| if (!email || !password) { | |
| addStatusMessage('Veuillez entrer un email et un mot de passe', 'error'); | |
| return; | |
| } | |
| // Simulation du processus de connexion | |
| loginBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Connexion...'; | |
| loginBtn.disabled = true; | |
| setTimeout(() => { | |
| addStatusMessage('Connecté avec succès à LinkedIn', 'success'); | |
| loginBtn.innerHTML = '<i class="fas fa-check mr-2"></i> Connecté'; | |
| statusSection.classList.remove('hidden'); | |
| }, 2000); | |
| }); | |
| // Bouton de démarrage de l'enregistrement | |
| startBtn.addEventListener('click', function() { | |
| const profileUrl = profileUrlInput.value.trim(); | |
| const duration = parseInt(durationSelect.value); | |
| if (!profileUrl) { | |
| addStatusMessage('Veuillez entrer une URL de profil', 'error'); | |
| return; | |
| } | |
| // Validation de l'URL | |
| if (!isValidLinkedInUrl(profileUrl)) { | |
| addStatusMessage('Veuillez entrer une URL de profil LinkedIn valide', 'error'); | |
| return; | |
| } | |
| // Simulation du processus d'enregistrement | |
| simulateRecording(duration); | |
| }); | |
| // Bouton de téléchargement | |
| downloadBtn.addEventListener('click', function() { | |
| addStatusMessage('Préparation du téléchargement...', 'info'); | |
| // Créer un lien de téléchargement simulé | |
| const link = document.createElement('a'); | |
| link.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent('Ceci est une simulation. Dans une application réelle, vous auriez ici votre vidéo.'); | |
| link.download = 'linkedin_recording_simulation.txt'; | |
| link.style.display = 'none'; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| setTimeout(() => { | |
| addStatusMessage('Téléchargement simulé terminé!', 'success'); | |
| }, 1500); | |
| }); | |
| // Bouton nouvel enregistrement | |
| newRecordingBtn.addEventListener('click', function() { | |
| previewSection.classList.add('hidden'); | |
| profileUrlInput.value = ''; | |
| startBtn.classList.add('opacity-50', 'cursor-not-allowed'); | |
| startBtn.disabled = true; | |
| statusMessages.innerHTML = ''; | |
| progressBar.style.width = '0%'; | |
| progressPercent.textContent = '0%'; | |
| fakeVideo.style.display = 'none'; | |
| videoPlaceholder.style.display = 'flex'; | |
| fakeVideo.pause(); | |
| fakeVideo.currentTime = 0; | |
| }); | |
| // Fonction pour ajouter des messages d'état | |
| function addStatusMessage(message, type) { | |
| const icon = { | |
| 'success': 'fa-check-circle', | |
| 'error': 'fa-times-circle', | |
| 'info': 'fa-info-circle', | |
| 'warning': 'fa-exclamation-circle' | |
| }[type]; | |
| const color = { | |
| 'success': 'text-green-600', | |
| 'error': 'text-red-600', | |
| 'info': 'text-blue-600', | |
| 'warning': 'text-yellow-600' | |
| }[type]; | |
| const messageEl = document.createElement('div'); | |
| messageEl.className = `flex items-start ${color}`; | |
| messageEl.innerHTML = ` | |
| <i class="fas ${icon} mt-1 mr-2"></i> | |
| <span>${message}</span> | |
| `; | |
| statusMessages.prepend(messageEl); | |
| } | |
| // Simulation du processus d'enregistrement | |
| function simulateRecording(duration) { | |
| startBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Traitement...'; | |
| startBtn.disabled = true; | |
| // Afficher la section d'état si cachée | |
| statusSection.classList.remove('hidden'); | |
| // Effacer les messages précédents sauf la connexion réussie | |
| if (statusMessages.children.length > 1) { | |
| statusMessages.innerHTML = statusMessages.children[0].outerHTML; | |
| } | |
| addStatusMessage('Navigation vers la page du profil...', 'info'); | |
| // Simulation de progression | |
| let progress = 0; | |
| const totalSteps = 100; | |
| const intervalTime = (duration * 1000) / (totalSteps / 5); // Ajuster pour la durée sélectionnée | |
| const interval = setInterval(() => { | |
| progress += 5; | |
| progressBar.style.width = `${progress}%`; | |
| progressPercent.textContent = `${progress}%`; | |
| // Mettre à jour les messages à certains points de progression | |
| if (progress === 20) { | |
| addStatusMessage('Page de profil chargée avec succès', 'success'); | |
| } else if (progress === 40) { | |
| addStatusMessage('Début de l\'enregistrement vidéo...', 'info'); | |
| } else if (progress === 60) { | |
| addStatusMessage('Défilement du profil...', 'info'); | |
| } else if (progress === 80) { | |
| addStatusMessage('Finalisation de l\'enregistrement...', 'info'); | |
| } | |
| // Terminer le processus | |
| if (progress >= 100) { | |
| clearInterval(interval); | |
| addStatusMessage('Enregistrement terminé!', 'success'); | |
| startBtn.innerHTML = '<i class="fas fa-check mr-2"></i> Terminé'; | |
| // Afficher la section d'aperçu avec une vidéo simulée | |
| setTimeout(() => { | |
| previewSection.classList.remove('hidden'); | |
| videoPlaceholder.style.display = 'none'; | |
| fakeVideo.style.display = 'block'; | |
| // Créer une vidéo simulée avec un canvas animé | |
| simulateVideoPlayback(); | |
| }, 500); | |
| } | |
| }, intervalTime); | |
| } | |
| // Simulation de lecture vidéo | |
| function simulateVideoPlayback() { | |
| // Créer un canvas animé comme simulation de vidéo | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = 640; | |
| canvas.height = 360; | |
| canvas.style.width = '100%'; | |
| canvas.style.height = '100%'; | |
| canvas.style.objectFit = 'cover'; | |
| const ctx = canvas.getContext('2d'); | |
| // Effacer le contenu précédent de la vidéo | |
| fakeVideo.innerHTML = ''; | |
| fakeVideo.appendChild(canvas); | |
| // Animation de défilement simulée | |
| let scrollPosition = 0; | |
| const scrollInterval = setInterval(() => { | |
| // Fond bleu LinkedIn | |
| ctx.fillStyle = '#f3f6f8'; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // Barre de navigation supérieure simulée | |
| ctx.fillStyle = '#0077b5'; | |
| ctx.fillRect(0, 0, canvas.width, 60); | |
| // Texte de simulation | |
| ctx.fillStyle = '#000'; | |
| ctx.font = '20px Arial'; | |
| ctx.fillText('Simulation de défilement LinkedIn', 20, 100 + scrollPosition); | |
| ctx.font = '16px Arial'; | |
| ctx.fillText('• Expérience professionnelle', 20, 140 + scrollPosition); | |
| ctx.fillText('• Formation', 20, 180 + scrollPosition); | |
| ctx.fillText('• Compétences', 20, 220 + scrollPosition); | |
| ctx.fillText('• Recommandations', 20, 260 + scrollPosition); | |
| ctx.fillText('• Publications', 20, 300 + scrollPosition); | |
| scrollPosition -= 2; | |
| if (scrollPosition < -300) { | |
| clearInterval(scrollInterval); | |
| } | |
| }, 50); | |
| fakeVideo.play(); // Lancer la lecture | |
| } | |
| // Validation simple d'URL LinkedIn | |
| function isValidLinkedInUrl(url) { | |
| return url.includes('linkedin.com/in/') && | |
| (url.startsWith('http://') || url.startsWith('https://')); | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Wizeo/test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |