Jensin commited on
Commit
2566d19
·
verified ·
1 Parent(s): 8f29d1d

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LinkedIn Profile Scraper | 10K Profiles per Batch</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"> <script> tailwind.config = { theme: { extend: { colors: { linkedin: '#0A66C2', primary: '#0A66C2', secondary: '#378FE9', accent: '#16437E', dark: '#1D2226', light: '#F5F5F5' } } } } </script> <style> .scraper-card { box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); border-radius: 16px; transition: all 0.3s ease; } .scraper-card:hover { transform: translateY(-5px); box-shadow: 0 20px 30px -10px rgba(0, 0, 0, 0.15); } .progress-bar { height: 8px; border-radius: 4px; overflow: hidden; background-color: #e0e0e0; } .progress-fill { height: 100%; border-radius: 4px; background: linear-gradient(90deg, #0A66C2, #378FE9); transition: width 0.5s ease; } .profile-card { transition: all 0.2s ease; border-left: 4px solid #0A66C2; } .profile-card:hover { transform: translateX(5px); background-color: #f8fafc; } .scrape-btn { background: linear-gradient(135deg, #0A66C2, #16437E); transition: all 0.3s ease; } .scrape-btn:hover { transform: scale(1.02); box-shadow: 0 10px 20px -5px rgba(10, 102, 194, 0.4); } .scrape-btn:active { transform: scale(0.98); } .tab-btn { transition: all 0.2s ease; border-bottom: 3px solid transparent; } .tab-btn.active { border-bottom-color: #0A66C2; color: #0A66C2; } .result-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; } @media (min-width: 640px) { .result-grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1.5rem; } } .animate-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .floating-notification { animation: floatUp 0.5s ease-out forwards; } @keyframes floatUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } </style> </head> <body class="bg-gray-50 min-h-screen"> <!-- Header --> <header class="bg-white shadow-sm"> <div class="container mx-auto px-4 py-4 flex justify-between items-center"> <div class="flex items-center"> <div class="bg-primary p-2 rounded-lg mr-3"> <i class="fab fa-linkedin text-white text-2xl"></i> </div> <h1 class="text-2xl font-bold text-gray-800">LinkedIn<span class="text-primary">Scraper</span></h1> </div> <nav> <ul class="hidden md:flex space-x-6"> <li><a href="#" class="text-gray-600 hover:text-primary font-medium">Dashboard</a></li> <li><a href="#" class="text-gray-600 hover:text-primary font-medium">Scrape History</a></li> <li><a href="#" class="text-gray-600 hover:text-primary font-medium">API</a></li> <li><a href="#" class="text-gray-600 hover:text-primary font-medium">Help</a></li> </ul> <button class="md:hidden text-gray-600"> <i class="fas fa-bars text-xl"></i> </button> </nav> <div class="flex items-center"> <button class="bg-primary hover:bg-secondary text-white px-4 py-2 rounded-lg font-medium flex items-center"> <i class="fas fa-user-plus mr-2"></i> Upgrade </button> <div class="ml-4 relative"> <div class="w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center cursor-pointer"> <i class="fas fa-user text-gray-600"></i> </div> </div> </div> </div> </header> <!-- Main Content --> <main class="container mx-auto px-4 py-8"> <div class="text-center mb-10"> <h2 class="text-4xl font-bold text-gray-800 mb-3">LinkedIn Profile Scraper</h2> <p class="text-xl text-gray-600 max-w-3xl mx-auto">Extract up to 10,000 LinkedIn profiles per batch with professional details including name, title, company, location, and more.</p> </div> <!-- Stats Cards --> <div class="grid grid-cols-2 sm:grid-cols-4 gap-4 sm:gap-6 mb-8"> <div class="scraper-card bg-white p-6 rounded-xl"> <div class="flex justify-between items-center"> <div> <p class="text-gray-500 text-sm">Total Scraped</p> <h3 class="text-2xl font-bold text-gray-800">124,856</h3> </div> <div class="bg-blue-100 p-3 rounded-lg"> <i class="fas fa-database text-primary text-xl"></i> </div> </div> </div> <div class="scraper-card bg-white p-6 rounded-xl"> <div class="flex justify-between items-center"> <div> <p class="text-gray-500 text-sm">This Month</p> <h3 class="text-2xl font-bold text-gray-800">8,420</h3> </div> <div class="bg-green-100 p-3 rounded-lg"> <i class="fas fa-chart-line text-green-500 text-xl"></i> </div> </div> </div> <div class="scraper-card bg-white p-6 rounded-xl"> <div class="flex justify-between items-center"> <div> <p class="text-gray-500 text-sm">Batch Size</p> <h3 class="text-2xl font-bold text-gray-800">10,000</h3> </div> <div class="bg-purple-100 p-3 rounded-lg"> <i class="fas fa-layer-group text-purple-500 text-xl"></i> </div> </div> </div> <div class="scraper-card bg-white p-6 rounded-xl"> <div class="flex justify-between items-center"> <div> <p class="text-gray-500 text-sm">Success Rate</p> <h3 class="text-2xl font-bold text-gray-800">98.7%</h3> </div> <div class="bg-yellow-100 p-3 rounded-lg"> <i class="fas fa-check-circle text-yellow-500 text-xl"></i> </div> </div> </div> </div> <!-- Scraper Interface --> <div class="scraper-card bg-white p-6 md:p-8 rounded-xl mb-8"> <div class="flex flex-wrap mb-6 border-b"> <button class="tab-btn px-4 py-2 font-medium text-gray-600 mr-4 active">New Scrape</button> <button class="tab-btn px-4 py-2 font-medium text-gray-600 mr-4">Saved Templates</button> <button class="tab-btn px-4 py-2 font-medium text-gray-600">Advanced Filters</button> </div> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6 mb-6"> <div> <label class="block text-gray-700 font-medium mb-2">Search Keywords</label> <input type="text" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent" placeholder="e.g., Software Engineer, Marketing Manager"> </div> <div> <label class="block text-gray-700 font-medium mb-2">Location</label> <input type="text" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent" placeholder="e.g., United States, San Francisco"> </div> <div> <label class="block text-gray-700 font-medium mb-2">Industry</label> <select class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"> <option value="">All Industries</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> <option value="healthcare">Healthcare</option> <option value="education">Education</option> <option value="marketing">Marketing</option> </select> </div> <div> <label class="block text-gray-700 font-medium mb-2">Company Size</label> <select class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"> <option value="">All Sizes</option> <option value="1-10">1-10 employees</option> <option value="11-50">11-50 employees</option> <option value="51-200">51-200 employees</option> <option value="201-500">201-500 employees</option> <option value="501+">501+ employees</option> </select> </div> </div> <div class="mb-6"> <label class="block text-gray-700 font-medium mb-2">Number of Profiles</label> <div class="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4"> <input type="range" min="100" max="10000" step="100" value="5000" class="w-full sm:mr-4" id="profileRange"> <div class="bg-gray-100 px-4 py-2 rounded-lg w-full sm:w-auto text-center"> <span id="profileCount">5,000</span> profiles </div> </div> <div class="text-sm text-gray-500 mt-2">Max 10,000 profiles per batch</div> </div> <div class="flex flex-wrap items-center justify-between"> <div class="flex items-center mb-4 md:mb-0"> <input type="checkbox" id="includeContact" class="mr-2 h-5 w-5 text-primary rounded focus:ring-primary"> <label for="includeContact" class="text-gray-700">Include contact information</label> </div> <button id="scrapeBtn" class="scrape-btn text-white px-8 py-3 rounded-lg font-semibold flex items-center w-full sm:w-auto justify-center"> <i class="fas fa-bolt mr-2"></i> Start Scraping </button> </div> </div> <!-- Progress Section --> <div id="progressSection" class="scraper-card bg-white p-6 md:p-8 rounded-xl mb-8 hidden"> <h3 class="text-xl font-bold text-gray-800 mb-4">Scraping in Progress</h3> <div class="mb-4"> <div class="flex justify-between mb-2"> <span class="text-gray-700">Extracting profiles...</span> <span id="progressPercent" class="text-primary font-medium">0%</span> </div> <div class="progress-bar"> <div id="progressFill" class="progress-fill" style="width: 0%"></div> </div> </div> <div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4 mt-6"> <div class="text-center p-4 bg-gray-50 rounded-lg"> <div class="text-2xl font-bold text-primary" id="profilesScraped">0</div> <div class="text-gray-600">Profiles Scraped</div> </div> <div class="text-center p-4 bg-gray-50 rounded-lg"> <div class="text-2xl font-bold text-green-500" id="successRate">0%</div> <div class="text-gray-600">Success Rate</div> </div> <div class="text-center p-4 bg-gray-50 rounded-lg"> <div class="text-2xl font-bold text-gray-800" id="timeElapsed">0s</div> <div class="text-gray-600">Time Elapsed</div> </div> <div class="text-center p-4 bg-gray-50 rounded-lg"> <div class="text-2xl font-bold text-gray-800" id="timeRemaining">~30s</div> <div class="text-gray-600">Estimated Time</div> </div> </div> </div> <!-- Results Section --> <div id="resultsSection" class="hidden"> <div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6"> <h3 class="text-2xl font-bold text-gray-800">Scraping Results</h3> <div class="flex flex-col sm:flex-row gap-2 sm:gap-3 w-full sm:w-auto"> <button class="bg-white border border-gray-300 px-4 py-2 rounded-lg font-medium flex items-center"> <i class="fas fa-download mr-2"></i> Export CSV </button> <button class="bg-white border border-gray-300 px-4 py-2 rounded-lg font-medium flex items-center"> <i class="fas fa-file-excel mr-2"></i> Export Excel </button> </div> </div> <div class="result-grid mb-8"> <!-- Profile cards will be inserted here by JavaScript --> </div> <div class="flex justify-between items-center bg-white p-4 rounded-lg"> <div class="text-gray-600"> Showing <span id="showingCount">10</span> of <span id="totalCount">5,000</span> profiles </div> <div class="flex flex-wrap justify-center gap-2"> <button class="px-4 py-2 bg-gray-100 rounded-lg"> <i class="fas fa-chevron-left"></i> </button> <button class="px-4 py-2 bg-primary text-white rounded-lg">1</button> <button class="px-4 py-2 bg-gray-100 rounded-lg">2</button> <button class="px-4 py-2 bg-gray-100 rounded-lg">3</button> <button class="px-4 py-2 bg-gray-100 rounded-lg">...</button> <button class="px-4 py-2 bg-gray-100 rounded-lg">50</button> <button class="px-4 py-2 bg-gray-100 rounded-lg"> <i class="fas fa-chevron-right"></i> </button> </div> </div> </div> <!-- Notification --> <div id="notification" class="fixed bottom-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg hidden"> <i class="fas fa-check-circle mr-2"></i> <span>Scraping completed successfully!</span> </div> </main> <!-- Footer --> <footer class="bg-dark text-gray-300 py-8 mt-12"> <div class="container mx-auto px-4"> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 sm:gap-8"> <div> <h4 class="text-white text-lg font-semibold mb-4">LinkedIn Scraper</h4> <p class="mb-4">Professional LinkedIn data extraction tool for recruiters, marketers, and sales professionals.</p> <div class="flex space-x-4"> <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-twitter"></i></a> <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-facebook"></i></a> <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-linkedin"></i></a> </div> </div> <div> <h4 class="text-white text-lg font-semibold mb-4">Features</h4> <ul class="space-y-2"> <li><a href="#" class="hover:text-white">Profile Scraping</a></li> <li><a href="#" class="hover:text-white">Company Data</a></li> <li><a href="#" class="hover:text-white">Email Extraction</a></li> <li><a href="#" class="hover:text-white">Bulk Processing</a></li> </ul> </div> <div> <h4 class="text-white text-lg font-semibold mb-4">Resources</h4> <ul class="space-y-2"> <li><a href="#" class="hover:text-white">Documentation</a></li> <li><a href="#" class="hover:text-white">API Reference</a></li> <li><a href="#" class="hover:text-white">Tutorials</a></li> <li><a href="#" class="hover:text-white">Blog</a></li> </ul> </div> <div> <h4 class="text-white text-lg font-semibold mb-4">Legal</h4> <ul class="space-y-2"> <li><a href="#" class="hover:text-white">Privacy Policy</a></li> <li><a href="#" class="hover:text-white">Terms of Service</a></li> <li><a href="#" class="hover:text-white">Compliance</a></li> <li><a href="#" class="hover:text-white">GDPR</a></li> </ul> </div> </div> <div class="border-t border-gray-700 mt-8 pt-6 text-center"> <p>© 2023 LinkedInScraper. All rights reserved.</p> </div> </div> </footer> <script> // DOM Elements const profileRange = document.getElementById('profileRange'); const profileCount = document.getElementById('profileCount'); const scrapeBtn = document.getElementById('scrapeBtn'); const progressSection = document.getElementById('progressSection'); const resultsSection = document.getElementById('resultsSection'); const progressFill = document.getElementById('progressFill'); const progressPercent = document.getElementById('progressPercent'); const profilesScraped = document.getElementById('profilesScraped'); const successRate = document.getElementById('successRate'); const timeElapsed = document.getElementById('timeElapsed'); const timeRemaining = document.getElementById('timeRemaining'); const notification = document.getElementById('notification'); const resultGrid = document.querySelector('.result-grid'); // Update profile count display profileRange.addEventListener('input', function() { const count = parseInt(this.value).toLocaleString(); profileCount.textContent = count; }); // Scrape button handler scrapeBtn.addEventListener('click', function() { // Show progress section progressSection.classList.remove('hidden'); // Hide results if shown resultsSection.classList.add('hidden'); // Reset progress let progress = 0; let elapsed = 0; let scraped = 0; const totalProfiles = parseInt(profileRange.value); const successPercent = 98 + Math.random() * 1.3; // Random success rate between 98-99.3% // Start progress simulation const interval = setInterval(() => { progress += 1; elapsed += 1; scraped = Math.floor(totalProfiles * (progress/100)); // Update progress bar progressFill.style.width = `${progress}%`; progressPercent.textContent = `${progress}%`; profilesScraped.textContent = scraped.toLocaleString(); successRate.textContent = `${successPercent.toFixed(1)}%`; timeElapsed.textContent = `${elapsed}s`; // Calculate remaining time const remaining = Math.max(1, Math.floor((100 - progress) * elapsed / progress)); timeRemaining.textContent = `~${remaining}s`; // When progress completes if (progress >= 100) { clearInterval(interval); // Show notification notification.classList.remove('hidden'); notification.classList.add('floating-notification'); // Hide notification after 3 seconds setTimeout(() => { notification.classList.add('hidden'); notification.classList.remove('floating-notification'); }, 3000); // Show results after a delay setTimeout(() => { progressSection.classList.add('hidden'); resultsSection.classList.remove('hidden'); populateResults(totalProfiles); }, 1000); } }, 50); // Update every 50ms }); // Populate results with mock data function populateResults(total) { // Clear existing results resultGrid.innerHTML = ''; // Update counts document.getElementById('showingCount').textContent = '10'; document.getElementById('totalCount').textContent = total.toLocaleString(); // Generate mock profile cards const titles = [ 'Senior Software Engineer', 'Marketing Director', 'Product Manager', 'Data Scientist', 'UX Designer', 'Sales Executive', 'HR Specialist', 'Financial Analyst', 'Operations Manager', 'Content Strategist' ]; const companies = [ 'Google', 'Microsoft', 'Amazon', 'Apple', 'Meta', 'Netflix', 'Adobe', 'Salesforce', 'IBM', 'Intel' ]; const locations = [ 'San Francisco, CA', 'New York, NY', 'Seattle, WA', 'Austin, TX', 'Boston, MA', 'Chicago, IL', 'Los Angeles, CA' ]; for (let i = 0; i < 10; i++) { const title = titles[Math.floor(Math.random() * titles.length)]; const company = companies[Math.floor(Math.random() * companies.length)]; const location = locations[Math.floor(Math.random() * locations.length)]; const card = document.createElement('div'); card.className = 'profile-card bg-white p-5 rounded-lg shadow-sm'; card.innerHTML = ` <div class="flex items-start mb-4"> <div class="bg-gray-200 border-2 border-dashed rounded-xl w-16 h-16" /> <div class="ml-4"> <h4 class="font-bold text-lg text-gray-800">${getRandomName()}</h4> <p class="text-gray-600">${title} at ${company}</p> </div> </div> <div class="grid grid-cols-2 gap-3 mb-4"> <div class="flex items-center"> <i class="fas fa-building text-gray-500 mr-2"></i> <span>${company}</span> </div> <div class="flex items-center"> <i class="fas fa-map-marker-alt text-gray-500 mr-2"></i> <span>${location}</span> </div> <div class="flex items-center"> <i class="fas fa-briefcase text-gray-500 mr-2"></i> <span>${Math.floor(Math.random() * 15) + 3} years exp</span> </div> <div class="flex items-center"> <i class="fas fa-user-friends text-gray-500 mr-2"></i> <span>${(Math.floor(Math.random() * 500) + 100).toLocaleString()}+ connections</span> </div> </div> <div class="flex justify-between"> <button class="text-primary hover:text-secondary font-medium"> <i class="fas fa-envelope mr-1"></i> Contact </button> <button class="text-gray-600 hover:text-gray-800"> <i class="fas fa-save mr-1"></i> Save Profile </button> </div> `; resultGrid.appendChild(card); } } // Generate random names function getRandomName() { const firstNames = ['James', 'Mary', 'John', 'Patricia', 'Robert', 'Jennifer', 'Michael', 'Linda', 'William', 'Elizabeth']; const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez']; const firstName = firstNames[Math.floor(Math.random() * firstNames.length)]; const lastName = lastNames[Math.floor(Math.random() * lastNames.length)]; return `${firstName} ${lastName}`; } </script> </body> </html> - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +843 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Linked Agent
3
- emoji: 💻
4
- colorFrom: pink
5
  colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: linked-agent
3
+ emoji: 🐳
4
+ colorFrom: blue
5
  colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,843 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LinkedIn Profile Scraper | 10K Profiles per Batch</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script>
10
+ tailwind.config = {
11
+ darkMode: 'class',
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ linkedin: '#0A66C2',
16
+ primary: '#0A66C2',
17
+ secondary: '#378FE9',
18
+ accent: '#16437E',
19
+ dark: '#1D2226',
20
+ light: '#F5F5F5',
21
+ darkBg: '#12181D',
22
+ darkCard: '#1D2933'
23
+ }
24
+ }
25
+ }
26
+ }
27
+ </script>
28
+ <style>
29
+ .scraper-card {
30
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
31
+ border-radius: 16px;
32
+ transition: all 0.3s ease;
33
+ }
34
+
35
+ .scraper-card:hover {
36
+ transform: translateY(-5px);
37
+ box-shadow: 0 20px 30px -10px rgba(0, 0, 0, 0.15);
38
+ }
39
+
40
+ .progress-bar {
41
+ height: 8px;
42
+ border-radius: 4px;
43
+ overflow: hidden;
44
+ background-color: #e0e0e0;
45
+ }
46
+
47
+ .progress-fill {
48
+ height: 100%;
49
+ border-radius: 4px;
50
+ background: linear-gradient(90deg, #0A66C2, #378FE9);
51
+ transition: width 0.5s ease;
52
+ }
53
+
54
+ .profile-card {
55
+ transition: all 0.2s ease;
56
+ border-left: 4px solid #0A66C2;
57
+ }
58
+
59
+ .profile-card:hover {
60
+ transform: translateX(5px);
61
+ background-color: #f8fafc;
62
+ }
63
+
64
+ .dark .profile-card:hover {
65
+ background-color: #1f2a33;
66
+ }
67
+
68
+ .scrape-btn {
69
+ background: linear-gradient(135deg, #0A66C2, #16437E);
70
+ transition: all 0.3s ease;
71
+ }
72
+
73
+ .scrape-btn:hover {
74
+ transform: scale(1.02);
75
+ box-shadow: 0 10px 20px -5px rgba(10, 102, 194, 0.4);
76
+ }
77
+
78
+ .scrape-btn:active {
79
+ transform: scale(0.98);
80
+ }
81
+
82
+ .tab-btn {
83
+ transition: all 0.2s ease;
84
+ border-bottom: 3px solid transparent;
85
+ }
86
+
87
+ .tab-btn.active {
88
+ border-bottom-color: #0A66C2;
89
+ color: #0A66C2;
90
+ }
91
+
92
+ .result-grid {
93
+ display: grid;
94
+ grid-template-columns: 1fr;
95
+ gap: 1rem;
96
+ }
97
+
98
+ @media (min-width: 640px) {
99
+ .result-grid {
100
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
101
+ gap: 1.5rem;
102
+ }
103
+ }
104
+
105
+ .animate-pulse {
106
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
107
+ }
108
+
109
+ @keyframes pulse {
110
+ 0%, 100% { opacity: 1; }
111
+ 50% { opacity: 0.5; }
112
+ }
113
+
114
+ .floating-notification {
115
+ animation: floatUp 0.5s ease-out forwards;
116
+ }
117
+
118
+ @keyframes floatUp {
119
+ from {
120
+ opacity: 0;
121
+ transform: translateY(20px);
122
+ }
123
+ to {
124
+ opacity: 1;
125
+ transform: translateY(0);
126
+ }
127
+ }
128
+
129
+ .skeleton {
130
+ background-color: #e2e8f0;
131
+ border-radius: 4px;
132
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
133
+ }
134
+
135
+ .dark .skeleton {
136
+ background-color: #2d3748;
137
+ }
138
+
139
+ .dark-mode-toggle {
140
+ transition: all 0.3s ease;
141
+ }
142
+
143
+ .dark-mode-toggle:hover {
144
+ transform: rotate(15deg);
145
+ }
146
+
147
+ .stat-card:hover .stat-icon {
148
+ transform: scale(1.1) rotate(5deg);
149
+ }
150
+
151
+ .stat-icon {
152
+ transition: all 0.3s ease;
153
+ }
154
+
155
+ .tooltip {
156
+ position: relative;
157
+ display: inline-block;
158
+ }
159
+
160
+ .tooltip .tooltip-text {
161
+ visibility: hidden;
162
+ width: 200px;
163
+ background-color: #1D2226;
164
+ color: #fff;
165
+ text-align: center;
166
+ border-radius: 6px;
167
+ padding: 8px;
168
+ position: absolute;
169
+ z-index: 1;
170
+ bottom: 125%;
171
+ left: 50%;
172
+ transform: translateX(-50%);
173
+ opacity: 0;
174
+ transition: opacity 0.3s;
175
+ font-size: 0.875rem;
176
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
177
+ }
178
+
179
+ .tooltip:hover .tooltip-text {
180
+ visibility: visible;
181
+ opacity: 1;
182
+ }
183
+
184
+ .dark .tooltip .tooltip-text {
185
+ background-color: #2d3748;
186
+ }
187
+
188
+ .mobile-menu {
189
+ transform: translateX(-100%);
190
+ transition: transform 0.3s ease;
191
+ }
192
+
193
+ .mobile-menu.open {
194
+ transform: translateX(0);
195
+ }
196
+
197
+ .export-btn {
198
+ transition: all 0.2s ease;
199
+ }
200
+
201
+ .export-btn:hover {
202
+ transform: translateY(-2px);
203
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
204
+ }
205
+
206
+ .pagination-btn {
207
+ transition: all 0.2s ease;
208
+ }
209
+
210
+ .pagination-btn:hover:not(.disabled) {
211
+ background-color: #e5e7eb;
212
+ transform: translateY(-2px);
213
+ }
214
+
215
+ .dark .pagination-btn:hover:not(.disabled) {
216
+ background-color: #2d3748;
217
+ }
218
+ </style>
219
+ </head>
220
+ <body class="bg-gray-50 min-h-screen dark:bg-darkBg">
221
+ <!-- Header -->
222
+ <header class="bg-white shadow-sm dark:bg-darkCard">
223
+ <div class="container mx-auto px-4 py-4 flex justify-between items-center">
224
+ <div class="flex items-center">
225
+ <div class="bg-primary p-2 rounded-lg mr-3">
226
+ <i class="fab fa-linkedin text-white text-2xl"></i>
227
+ </div>
228
+ <h1 class="text-2xl font-bold text-gray-800 dark:text-gray-200">LinkedIn<span class="text-primary">Scraper</span></h1>
229
+ </div>
230
+ <nav>
231
+ <ul class="hidden md:flex space-x-6">
232
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Dashboard</a></li>
233
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Scrape History</a></li>
234
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">API</a></li>
235
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Help</a></li>
236
+ </ul>
237
+ <button id="mobileMenuBtn" class="md:hidden text-gray-600 dark:text-gray-300">
238
+ <i class="fas fa-bars text-xl"></i>
239
+ </button>
240
+ </nav>
241
+ <div class="flex items-center">
242
+ <button class="bg-primary hover:bg-secondary text-white px-4 py-2 rounded-lg font-medium flex items-center mr-4">
243
+ <i class="fas fa-user-plus mr-2"></i> Upgrade
244
+ </button>
245
+ <button id="darkModeToggle" class="dark-mode-toggle bg-gray-200 dark:bg-gray-700 p-2 rounded-full mr-4">
246
+ <i class="fas fa-moon text-gray-700 dark:text-yellow-300"></i>
247
+ </button>
248
+ <div class="relative">
249
+ <div class="w-10 h-10 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center cursor-pointer">
250
+ <i class="fas fa-user text-gray-600 dark:text-gray-300"></i>
251
+ </div>
252
+ <div class="absolute right-0 bottom-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white dark:border-darkCard"></div>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </header>
257
+
258
+ <!-- Mobile Menu -->
259
+ <div id="mobileMenu" class="mobile-menu fixed inset-0 z-50 bg-black bg-opacity-50 hidden">
260
+ <div class="bg-white dark:bg-darkCard w-64 h-full p-4">
261
+ <div class="flex justify-between items-center mb-8">
262
+ <h3 class="text-xl font-bold text-gray-800 dark:text-gray-200">Menu</h3>
263
+ <button id="closeMobileMenu" class="p-2 text-gray-600 dark:text-gray-300">
264
+ <i class="fas fa-times text-xl"></i>
265
+ </button>
266
+ </div>
267
+ <ul class="space-y-4">
268
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Dashboard</a></li>
269
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Scrape History</a></li>
270
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">API</a></li>
271
+ <li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Help</a></li>
272
+ <li class="pt-4">
273
+ <button class="bg-primary hover:bg-secondary text-white px-4 py-2 rounded-lg font-medium flex items-center w-full">
274
+ <i class="fas fa-user-plus mr-2"></i> Upgrade Account
275
+ </button>
276
+ </li>
277
+ </ul>
278
+ </div>
279
+ </div>
280
+
281
+ <!-- Main Content -->
282
+ <main class="container mx-auto px-4 py-8">
283
+ <div class="text-center mb-10">
284
+ <h2 class="text-4xl font-bold text-gray-800 dark:text-gray-200 mb-3">LinkedIn Profile Scraper</h2>
285
+ <p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">Extract up to 10,000 LinkedIn profiles per batch with professional details including name, title, company, location, and more.</p>
286
+ </div>
287
+
288
+ <!-- Stats Cards -->
289
+ <div class="grid grid-cols-2 sm:grid-cols-4 gap-4 sm:gap-6 mb-8">
290
+ <div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
291
+ <div class="flex justify-between items-center">
292
+ <div>
293
+ <p class="text-gray-500 dark:text-gray-400 text-sm">Total Scraped</p>
294
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">124,856</h3>
295
+ </div>
296
+ <div class="bg-blue-100 dark:bg-blue-900 p-3 rounded-lg">
297
+ <i class="fas fa-database text-primary dark:text-blue-300 text-xl stat-icon"></i>
298
+ </div>
299
+ </div>
300
+ </div>
301
+
302
+ <div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
303
+ <div class="flex justify-between items-center">
304
+ <div>
305
+ <p class="text-gray-500 dark:text-gray-400 text-sm">This Month</p>
306
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">8,420</h3>
307
+ </div>
308
+ <div class="bg-green-100 dark:bg-green-900 p-3 rounded-lg">
309
+ <i class="fas fa-chart-line text-green-500 dark:text-green-300 text-xl stat-icon"></i>
310
+ </div>
311
+ </div>
312
+ </div>
313
+
314
+ <div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
315
+ <div class="flex justify-between items-center">
316
+ <div>
317
+ <p class="text-gray-500 dark:text-gray-400 text-sm">Batch Size</p>
318
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">10,000</h3>
319
+ </div>
320
+ <div class="bg-purple-100 dark:bg-purple-900 p-3 rounded-lg">
321
+ <i class="fas fa-layer-group text-purple-500 dark:text-purple-300 text-xl stat-icon"></i>
322
+ </div>
323
+ </div>
324
+ </div>
325
+
326
+ <div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
327
+ <div class="flex justify-between items-center">
328
+ <div>
329
+ <p class="text-gray-500 dark:text-gray-400 text-sm">Success Rate</p>
330
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">98.7%</h3>
331
+ </div>
332
+ <div class="bg-yellow-100 dark:bg-yellow-900 p-3 rounded-lg">
333
+ <i class="fas fa-check-circle text-yellow-500 dark:text-yellow-300 text-xl stat-icon"></i>
334
+ </div>
335
+ </div>
336
+ </div>
337
+ </div>
338
+
339
+ <!-- Scraper Interface -->
340
+ <div class="scraper-card bg-white dark:bg-darkCard p-6 md:p-8 rounded-xl mb-8">
341
+ <div class="flex flex-wrap mb-6 border-b dark:border-gray-700">
342
+ <button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300 mr-4 active">New Scrape</button>
343
+ <button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300 mr-4">Saved Templates</button>
344
+ <button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300">Advanced Filters</button>
345
+ </div>
346
+
347
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6 mb-6">
348
+ <div>
349
+ <label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Search Keywords</label>
350
+ <input type="text" class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200" placeholder="e.g., Software Engineer, Marketing Manager">
351
+ </div>
352
+
353
+ <div>
354
+ <label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Location</label>
355
+ <input type="text" class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200" placeholder="e.g., United States, San Francisco">
356
+ </div>
357
+
358
+ <div>
359
+ <label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Industry</label>
360
+ <select class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200">
361
+ <option value="">All Industries</option>
362
+ <option value="it">Information Technology</option>
363
+ <option value="finance">Finance</option>
364
+ <option value="healthcare">Healthcare</option>
365
+ <option value="education">Education</option>
366
+ <option value="marketing">Marketing</option>
367
+ </select>
368
+ </div>
369
+
370
+ <div>
371
+ <label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Company Size</label>
372
+ <select class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200">
373
+ <option value="">All Sizes</option>
374
+ <option value="1-10">1-10 employees</option>
375
+ <option value="11-50">11-50 employees</option>
376
+ <option value="51-200">51-200 employees</option>
377
+ <option value="201-500">201-500 employees</option>
378
+ <option value="501+">501+ employees</option>
379
+ </select>
380
+ </div>
381
+ </div>
382
+
383
+ <div class="mb-6">
384
+ <label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Number of Profiles</label>
385
+ <div class="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4">
386
+ <input type="range" min="100" max="10000" step="100" value="5000" class="w-full sm:mr-4 dark:accent-primary" id="profileRange">
387
+ <div class="bg-gray-100 dark:bg-gray-800 px-4 py-2 rounded-lg w-full sm:w-auto text-center dark:text-gray-200">
388
+ <span id="profileCount">5,000</span> profiles
389
+ </div>
390
+ </div>
391
+ <div class="text-sm text-gray-500 dark:text-gray-400 mt-2">Max 10,000 profiles per batch</div>
392
+ </div>
393
+
394
+ <div class="flex flex-wrap items-center justify-between">
395
+ <div class="flex items-center mb-4 md:mb-0">
396
+ <input type="checkbox" id="includeContact" class="mr-2 h-5 w-5 text-primary rounded focus:ring-primary dark:bg-gray-800">
397
+ <label for="includeContact" class="text-gray-700 dark:text-gray-300">Include contact information</label>
398
+ </div>
399
+
400
+ <button id="scrapeBtn" class="scrape-btn text-white px-8 py-3 rounded-lg font-semibold flex items-center w-full sm:w-auto justify-center">
401
+ <i class="fas fa-bolt mr-2"></i>
402
+ <span id="scrapeBtnText">Start Scraping</span>
403
+ <span id="scrapeSpinner" class="ml-2 hidden">
404
+ <i class="fas fa-spinner fa-spin"></i>
405
+ </span>
406
+ </button>
407
+ </div>
408
+ </div>
409
+
410
+ <!-- Progress Section -->
411
+ <div id="progressSection" class="scraper-card bg-white dark:bg-darkCard p-6 md:p-8 rounded-xl mb-8 hidden">
412
+ <h3 class="text-xl font-bold text-gray-800 dark:text-gray-200 mb-4">Scraping in Progress</h3>
413
+ <div class="mb-4">
414
+ <div class="flex justify-between mb-2">
415
+ <span class="text-gray-700 dark:text-gray-300">Extracting profiles...</span>
416
+ <span id="progressPercent" class="text-primary font-medium">0%</span>
417
+ </div>
418
+ <div class="progress-bar">
419
+ <div id="progressFill" class="progress-fill" style="width: 0%"></div>
420
+ </div>
421
+ </div>
422
+
423
+ <div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4 mt-6">
424
+ <div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
425
+ <div class="text-2xl font-bold text-primary" id="profilesScraped">0</div>
426
+ <div class="text-gray-600 dark:text-gray-400">Profiles Scraped</div>
427
+ </div>
428
+ <div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
429
+ <div class="text-2xl font-bold text-green-500" id="successRate">0%</div>
430
+ <div class="text-gray-600 dark:text-gray-400">Success Rate</div>
431
+ </div>
432
+ <div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
433
+ <div class="text-2xl font-bold text-gray-800 dark:text-gray-200" id="timeElapsed">0s</div>
434
+ <div class="text-gray-600 dark:text-gray-400">Time Elapsed</div>
435
+ </div>
436
+ <div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
437
+ <div class="text-2xl font-bold text-gray-800 dark:text-gray-200" id="timeRemaining">~30s</div>
438
+ <div class="text-gray-600 dark:text-gray-400">Estimated Time</div>
439
+ </div>
440
+ </div>
441
+ </div>
442
+
443
+ <!-- Results Section -->
444
+ <div id="resultsSection" class="hidden">
445
+ <div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6">
446
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">Scraping Results</h3>
447
+ <div class="flex flex-col sm:flex-row gap-2 sm:gap-3 w-full sm:w-auto">
448
+ <button class="export-btn bg-white dark:bg-darkCard border border-gray-300 dark:border-gray-700 px-4 py-2 rounded-lg font-medium flex items-center justify-center">
449
+ <i class="fas fa-download mr-2"></i> Export CSV
450
+ </button>
451
+ <button class="export-btn bg-white dark:bg-darkCard border border-gray-300 dark:border-gray-700 px-4 py-2 rounded-lg font-medium flex items-center justify-center">
452
+ <i class="fas fa-file-excel mr-2"></i> Export Excel
453
+ </button>
454
+ </div>
455
+ </div>
456
+
457
+ <div class="result-grid mb-8" id="resultGrid">
458
+ <!-- Profile cards will be inserted here by JavaScript -->
459
+ </div>
460
+
461
+ <div class="flex flex-col sm:flex-row justify-between items-center bg-white dark:bg-darkCard p-4 rounded-lg">
462
+ <div class="text-gray-600 dark:text-gray-400 mb-4 sm:mb-0">
463
+ Showing <span id="showingCount">10</span> of <span id="totalCount">5,000</span> profiles
464
+ </div>
465
+ <div class="flex flex-wrap justify-center gap-2">
466
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed" id="prevPageBtn" disabled>
467
+ <i class="fas fa-chevron-left"></i>
468
+ </button>
469
+ <button class="pagination-btn px-4 py-2 bg-primary text-white rounded-lg">1</button>
470
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">2</button>
471
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">3</button>
472
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">...</button>
473
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">50</button>
474
+ <button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg" id="nextPageBtn">
475
+ <i class="fas fa-chevron-right"></i>
476
+ </button>
477
+ </div>
478
+ </div>
479
+ </div>
480
+
481
+ <!-- Notification -->
482
+ <div id="notification" class="fixed bottom-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg hidden">
483
+ <i class="fas fa-check-circle mr-2"></i>
484
+ <span>Scraping completed successfully!</span>
485
+ </div>
486
+ </main>
487
+
488
+ <!-- Footer -->
489
+ <footer class="bg-dark text-gray-300 py-8 mt-12">
490
+ <div class="container mx-auto px-4">
491
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 sm:gap-8">
492
+ <div>
493
+ <h4 class="text-white text-lg font-semibold mb-4">LinkedIn Scraper</h4>
494
+ <p class="mb-4">Professional LinkedIn data extraction tool for recruiters, marketers, and sales professionals.</p>
495
+ <div class="flex space-x-4">
496
+ <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-twitter"></i></a>
497
+ <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-facebook"></i></a>
498
+ <a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-linkedin"></i></a>
499
+ </div>
500
+ </div>
501
+
502
+ <div>
503
+ <h4 class="text-white text-lg font-semibold mb-4">Features</h4>
504
+ <ul class="space-y-2">
505
+ <li><a href="#" class="hover:text-white">Profile Scraping</a></li>
506
+ <li><a href="#" class="hover:text-white">Company Data</a></li>
507
+ <li><a href="#" class="hover:text-white">Email Extraction</a></li>
508
+ <li><a href="#" class="hover:text-white">Bulk Processing</a></li>
509
+ </ul>
510
+ </div>
511
+
512
+ <div>
513
+ <h4 class="text-white text-lg font-semibold mb-4">Resources</h4>
514
+ <ul class="space-y-2">
515
+ <li><a href="#" class="hover:text-white">Documentation</a></li>
516
+ <li><a href="#" class="hover:text-white">API Reference</a></li>
517
+ <li><a href="#" class="hover:text-white">Tutorials</a></li>
518
+ <li><a href="#" class="hover:text-white">Blog</a></li>
519
+ </ul>
520
+ </div>
521
+
522
+ <div>
523
+ <h4 class="text-white text-lg font-semibold mb-4">Legal</h4>
524
+ <ul class="space-y-2">
525
+ <li><a href="#" class="hover:text-white">Privacy Policy</a></li>
526
+ <li><a href="#" class="hover:text-white">Terms of Service</a></li>
527
+ <li><a href="#" class="hover:text-white">Compliance</a></li>
528
+ <li><a href="#" class="hover:text-white">GDPR</a></li>
529
+ </ul>
530
+ </div>
531
+ </div>
532
+
533
+ <div class="border-t border-gray-700 mt-8 pt-6 text-center">
534
+ <p>&copy; 2023 LinkedInScraper. All rights reserved.</p>
535
+ </div>
536
+ </div>
537
+ </footer>
538
+
539
+ <script>
540
+ // DOM Elements
541
+ const profileRange = document.getElementById('profileRange');
542
+ const profileCount = document.getElementById('profileCount');
543
+ const scrapeBtn = document.getElementById('scrapeBtn');
544
+ const scrapeBtnText = document.getElementById('scrapeBtnText');
545
+ const scrapeSpinner = document.getElementById('scrapeSpinner');
546
+ const progressSection = document.getElementById('progressSection');
547
+ const resultsSection = document.getElementById('resultsSection');
548
+ const progressFill = document.getElementById('progressFill');
549
+ const progressPercent = document.getElementById('progressPercent');
550
+ const profilesScraped = document.getElementById('profilesScraped');
551
+ const successRate = document.getElementById('successRate');
552
+ const timeElapsed = document.getElementById('timeElapsed');
553
+ const timeRemaining = document.getElementById('timeRemaining');
554
+ const notification = document.getElementById('notification');
555
+ const resultGrid = document.getElementById('resultGrid');
556
+ const darkModeToggle = document.getElementById('darkModeToggle');
557
+ const mobileMenuBtn = document.getElementById('mobileMenuBtn');
558
+ const mobileMenu = document.getElementById('mobileMenu');
559
+ const closeMobileMenu = document.getElementById('closeMobileMenu');
560
+ const prevPageBtn = document.getElementById('prevPageBtn');
561
+ const nextPageBtn = document.getElementById('nextPageBtn');
562
+ const showingCount = document.getElementById('showingCount');
563
+ const totalCount = document.getElementById('totalCount');
564
+
565
+ // Update profile count display
566
+ profileRange.addEventListener('input', function() {
567
+ const count = parseInt(this.value).toLocaleString();
568
+ profileCount.textContent = count;
569
+ });
570
+
571
+ // Dark mode toggle
572
+ darkModeToggle.addEventListener('click', function() {
573
+ document.documentElement.classList.toggle('dark');
574
+ const isDark = document.documentElement.classList.contains('dark');
575
+ localStorage.setItem('darkMode', isDark);
576
+
577
+ // Update icon
578
+ const icon = darkModeToggle.querySelector('i');
579
+ if (isDark) {
580
+ icon.classList.remove('fa-moon');
581
+ icon.classList.add('fa-sun');
582
+ } else {
583
+ icon.classList.remove('fa-sun');
584
+ icon.classList.add('fa-moon');
585
+ }
586
+ });
587
+
588
+ // Check for saved dark mode preference
589
+ if (localStorage.getItem('darkMode') === 'true') {
590
+ document.documentElement.classList.add('dark');
591
+ const icon = darkModeToggle.querySelector('i');
592
+ icon.classList.remove('fa-moon');
593
+ icon.classList.add('fa-sun');
594
+ }
595
+
596
+ // Mobile menu toggle
597
+ mobileMenuBtn.addEventListener('click', function() {
598
+ mobileMenu.classList.remove('hidden');
599
+ setTimeout(() => {
600
+ mobileMenu.classList.add('open');
601
+ }, 10);
602
+ });
603
+
604
+ closeMobileMenu.addEventListener('click', function() {
605
+ mobileMenu.classList.remove('open');
606
+ setTimeout(() => {
607
+ mobileMenu.classList.add('hidden');
608
+ }, 300);
609
+ });
610
+
611
+ // Close mobile menu when clicking outside
612
+ mobileMenu.addEventListener('click', function(e) {
613
+ if (e.target === mobileMenu) {
614
+ mobileMenu.classList.remove('open');
615
+ setTimeout(() => {
616
+ mobileMenu.classList.add('hidden');
617
+ }, 300);
618
+ }
619
+ });
620
+
621
+ // Scrape button handler
622
+ scrapeBtn.addEventListener('click', function() {
623
+ // Show spinner and change text
624
+ scrapeSpinner.classList.remove('hidden');
625
+ scrapeBtnText.textContent = 'Scraping...';
626
+ scrapeBtn.disabled = true;
627
+
628
+ // Show progress section
629
+ progressSection.classList.remove('hidden');
630
+
631
+ // Hide results if shown
632
+ resultsSection.classList.add('hidden');
633
+
634
+ // Reset progress
635
+ let progress = 0;
636
+ let elapsed = 0;
637
+ let scraped = 0;
638
+ const totalProfiles = parseInt(profileRange.value);
639
+ const successPercent = 98 + Math.random() * 1.3; // Random success rate between 98-99.3%
640
+
641
+ // Show skeleton loaders
642
+ showSkeletonLoaders(totalProfiles);
643
+
644
+ // Start progress simulation
645
+ const interval = setInterval(() => {
646
+ progress += 1;
647
+ elapsed += 1;
648
+ scraped = Math.floor(totalProfiles * (progress/100));
649
+
650
+ // Update progress bar
651
+ progressFill.style.width = `${progress}%`;
652
+ progressPercent.textContent = `${progress}%`;
653
+ profilesScraped.textContent = scraped.toLocaleString();
654
+ successRate.textContent = `${successPercent.toFixed(1)}%`;
655
+ timeElapsed.textContent = `${elapsed}s`;
656
+
657
+ // Calculate remaining time
658
+ const remaining = Math.max(1, Math.floor((100 - progress) * elapsed / progress));
659
+ timeRemaining.textContent = `~${remaining}s`;
660
+
661
+ // When progress completes
662
+ if (progress >= 100) {
663
+ clearInterval(interval);
664
+
665
+ // Reset button
666
+ scrapeSpinner.classList.add('hidden');
667
+ scrapeBtnText.textContent = 'Start Scraping';
668
+ scrapeBtn.disabled = false;
669
+
670
+ // Show notification
671
+ notification.classList.remove('hidden');
672
+ notification.classList.add('floating-notification');
673
+
674
+ // Hide notification after 3 seconds
675
+ setTimeout(() => {
676
+ notification.classList.add('hidden');
677
+ notification.classList.remove('floating-notification');
678
+ }, 3000);
679
+
680
+ // Show results after a delay
681
+ setTimeout(() => {
682
+ progressSection.classList.add('hidden');
683
+ resultsSection.classList.remove('hidden');
684
+ populateResults(totalProfiles);
685
+ }, 1000);
686
+ }
687
+ }, 50); // Update every 50ms
688
+ });
689
+
690
+ // Show skeleton loaders
691
+ function showSkeletonLoaders(total) {
692
+ resultGrid.innerHTML = '';
693
+
694
+ // Update counts
695
+ showingCount.textContent = '10';
696
+ totalCount.textContent = total.toLocaleString();
697
+
698
+ // Generate skeleton cards
699
+ for (let i = 0; i < 10; i++) {
700
+ const card = document.createElement('div');
701
+ card.className = 'profile-card bg-white dark:bg-darkCard p-5 rounded-lg shadow-sm';
702
+ card.innerHTML = `
703
+ <div class="flex items-start mb-4">
704
+ <div class="skeleton w-16 h-16 rounded-full"></div>
705
+ <div class="ml-4 flex-1">
706
+ <div class="skeleton h-5 w-3/4 mb-2"></div>
707
+ <div class="skeleton h-4 w-1/2"></div>
708
+ </div>
709
+ </div>
710
+ <div class="grid grid-cols-2 gap-3 mb-4">
711
+ <div class="flex items-center">
712
+ <div class="skeleton w-4 h-4 mr-2"></div>
713
+ <div class="skeleton h-4 w-3/4"></div>
714
+ </div>
715
+ <div class="flex items-center">
716
+ <div class="skeleton w-4 h-4 mr-2"></div>
717
+ <div class="skeleton h-4 w-3/4"></div>
718
+ </div>
719
+ <div class="flex items-center">
720
+ <div class="skeleton w-4 h-4 mr-2"></div>
721
+ <div class="skeleton h-4 w-3/4"></div>
722
+ </div>
723
+ <div class="flex items-center">
724
+ <div class="skeleton w-4 h-4 mr-2"></div>
725
+ <div class="skeleton h-4 w-3/4"></div>
726
+ </div>
727
+ </div>
728
+ <div class="flex justify-between">
729
+ <div class="skeleton h-8 w-24"></div>
730
+ <div class="skeleton h-8 w-24"></div>
731
+ </div>
732
+ `;
733
+
734
+ resultGrid.appendChild(card);
735
+ }
736
+ }
737
+
738
+ // Populate results with mock data
739
+ function populateResults(total) {
740
+ // Clear existing results
741
+ resultGrid.innerHTML = '';
742
+
743
+ // Update counts
744
+ showingCount.textContent = '10';
745
+ totalCount.textContent = total.toLocaleString();
746
+
747
+ // Generate mock profile cards
748
+ const titles = [
749
+ 'Senior Software Engineer',
750
+ 'Marketing Director',
751
+ 'Product Manager',
752
+ 'Data Scientist',
753
+ 'UX Designer',
754
+ 'Sales Executive',
755
+ 'HR Specialist',
756
+ 'Financial Analyst',
757
+ 'Operations Manager',
758
+ 'Content Strategist'
759
+ ];
760
+
761
+ const companies = [
762
+ 'Google', 'Microsoft', 'Amazon', 'Apple', 'Meta',
763
+ 'Netflix', 'Adobe', 'Salesforce', 'IBM', 'Intel'
764
+ ];
765
+
766
+ const locations = [
767
+ 'San Francisco, CA', 'New York, NY', 'Seattle, WA',
768
+ 'Austin, TX', 'Boston, MA', 'Chicago, IL', 'Los Angeles, CA'
769
+ ];
770
+
771
+ for (let i = 0; i < 10; i++) {
772
+ const title = titles[Math.floor(Math.random() * titles.length)];
773
+ const company = companies[Math.floor(Math.random() * companies.length)];
774
+ const location = locations[Math.floor(Math.random() * locations.length)];
775
+
776
+ const card = document.createElement('div');
777
+ card.className = 'profile-card bg-white dark:bg-darkCard p-5 rounded-lg shadow-sm';
778
+ card.innerHTML = `
779
+ <div class="flex items-start mb-4">
780
+ <div class="bg-gray-200 dark:bg-gray-700 rounded-xl w-16 h-16 flex items-center justify-center">
781
+ <i class="fas fa-user text-gray-500 dark:text-gray-400 text-xl"></i>
782
+ </div>
783
+ <div class="ml-4">
784
+ <h4 class="font-bold text-lg text-gray-800 dark:text-gray-200">${getRandomName()}</h4>
785
+ <p class="text-gray-600 dark:text-gray-400">${title} at ${company}</p>
786
+ </div>
787
+ </div>
788
+ <div class="grid grid-cols-2 gap-3 mb-4">
789
+ <div class="flex items-center">
790
+ <i class="fas fa-building text-gray-500 dark:text-gray-400 mr-2"></i>
791
+ <span class="text-gray-700 dark:text-gray-300">${company}</span>
792
+ </div>
793
+ <div class="flex items-center">
794
+ <i class="fas fa-map-marker-alt text-gray-500 dark:text-gray-400 mr-2"></i>
795
+ <span class="text-gray-700 dark:text-gray-300">${location}</span>
796
+ </div>
797
+ <div class="flex items-center">
798
+ <i class="fas fa-briefcase text-gray-500 dark:text-gray-400 mr-2"></i>
799
+ <span class="text-gray-700 dark:text-gray-300">${Math.floor(Math.random() * 15) + 3} years exp</span>
800
+ </div>
801
+ <div class="flex items-center">
802
+ <i class="fas fa-user-friends text-gray-500 dark:text-gray-400 mr-2"></i>
803
+ <span class="text-gray-700 dark:text-gray-300">${(Math.floor(Math.random() * 500) + 100).toLocaleString()}+ connections</span>
804
+ </div>
805
+ </div>
806
+ <div class="flex justify-between">
807
+ <button class="text-primary hover:text-secondary font-medium">
808
+ <i class="fas fa-envelope mr-1"></i> Contact
809
+ </button>
810
+ <button class="text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200">
811
+ <i class="fas fa-save mr-1"></i> Save Profile
812
+ </button>
813
+ </div>
814
+ `;
815
+
816
+ resultGrid.appendChild(card);
817
+ }
818
+ }
819
+
820
+ // Generate random names
821
+ function getRandomName() {
822
+ const firstNames = ['James', 'Mary', 'John', 'Patricia', 'Robert', 'Jennifer', 'Michael', 'Linda', 'William', 'Elizabeth'];
823
+ const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez'];
824
+
825
+ const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
826
+ const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
827
+
828
+ return `${firstName} ${lastName}`;
829
+ }
830
+
831
+ // Pagination functionality
832
+ prevPageBtn.addEventListener('click', function() {
833
+ // In a real app, this would fetch previous page data
834
+ alert('Previous page functionality would be implemented here');
835
+ });
836
+
837
+ nextPageBtn.addEventListener('click', function() {
838
+ // In a real app, this would fetch next page data
839
+ alert('Next page functionality would be implemented here');
840
+ });
841
+ </script>
842
+ <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=Jensin/linked-agent" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
843
+ </html>