Spaces:
Running
Running
<!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- README.md +6 -4
- index.html +843 -19
README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
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 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>© 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>
|