bbkdevops commited on
Commit
3e941e3
·
verified ·
1 Parent(s): 06a5ee3

#!/bin/bash

set -e

echo "🚀 Starting Social Media Data Collection System Installation..."

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
    OS="linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
    OS="macos"
else
    echo "❌ Unsupported OS"
    exit 1
fi

if ! command -v go &> /dev/null; then
    if [[ "$OS" == "linux" ]]; then
        sudo apt update
        sudo apt install -y golang-go
    elif [[ "$OS" == "macos" ]]; then
        brew install go
    fi
fi

if [[ "$OS" == "linux" ]]; then
    wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
    sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
    sudo apt update
    sudo apt install -y google-chrome-stable
elif [[ "$OS" == "macos" ]]; then
    brew install --cask google-chrome
fi

go install github.com/chromedp/chromedp@latest
go install github.com/gin-gonic/gin@latest
go install github.com/gorilla/websocket@latest
go install github.com/sashabaranov/go-openai@latest
go install golang.org/x/net/proxy@latest

mkdir -p social-scraper/{src,bin,logs,data,config}
cd social-scraper

cat > src/main.go << 'EOF'
package main

import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
"sync"
"time"

"github.com/chromedp/chromedp"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"github.com/sashabaranov/go-openai"
"golang.org/x/net/proxy"
)

type SocialScraper struct {
ctx           context.Context
cancel        context.CancelFunc
client        *http.Client
browser       *chromedp.RemoteRunner
mutex         sync.RWMutex
scrapedData   []map[string]interface{}
failedUrls    map[string]bool
successCount  int
errorCount    int
config        ScraperConfig
aiClient      *openai.Client
taskQueue     chan Task
resultChan    chan TaskResult
workerCount   int
}

type ScraperConfig struct {
Headless             bool
MaxConcurrency       int
RetryAttempts        int
DelayBetweenRequests time.Duration
UserAgents           []string
EnableCloudflare     bool
EnableStealth        bool
ProxyURL             string
OpenAIKey            string
DataDir              string
LogDir               string
}

type Task struct {
URL       string
Timestamp time.Time
}

type TaskResult struct {
URL      string                 `json:"url"`
Data     []map[string]interface{} `json:"data"`
Success  bool                   `json:"success"`
Error    string                 `json:"error,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}

type ChatMessage struct {
Role    string `json:"role"`
Content string `json:"content"`
}

type ChatResponse struct {
ID      string    `json:"id"`
Object  string    `json:"object"`
Created int64     `json:"created"`
Model   string    `json:"model"`
Choices []Choice  `json:"choices"`
}

type Choice struct {
Index        int     `json:"index"`
Message      Message `json:"message"`
FinishReason string  `json:"finish_reason"`
}

type Message struct {
Role    string `json:"role"`
Content string `json:"content"`
}

var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}

var scraper *SocialScraper
var wsConnections = make(map[*websocket.Conn]bool)
var wsMutex sync.RWMutex

func main() {
config := loadConfig()
createDirectories(config)
scraper = NewSocialScraper(config)
err := scraper.Initialize()
if err != nil {
log.Fatal("Failed to initialize scraper:", err)
}
scraper.StartWorkers()

r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{})
})
r.POST("/scrape", func(c *gin.Context) {
var requestData struct {
URLs []string `json:"urls"`
}
if err := c.ShouldBindJSON(&requestData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for _, url := range requestData.URLs {
scraper.taskQueue <- Task{
URL:       url,
Timestamp: time.Now(),
}
}
c.JSON(http.StatusOK, gin.H{"status": "queued", "count": len(requestData.URLs)})
})
r.GET("/ws", func(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
defer conn.Close()
wsMutex.Lock()
wsConnections[conn] = true
wsMutex.Unlock()
for {
var msg ChatMessage
err := conn.ReadJSON(&msg)
if err != nil {
log.Println("read:", err)
break
}
response, err := scraper.ChatWithAI(msg.Content)
if err != nil {
response = "Sorry, I encountered an error processing your request."
}
err = conn.WriteJSON(ChatResponse{
ID:      "chatcmpl-" + fmt.Sprintf("%d", time.Now().Unix()),
Object:  "chat.completion",
Created: time.Now().Unix(),
Model:   "gpt-4",
Choices: []Choice{
{
Index: 0,
Message: Message{
Role:    "assistant",
Content: response,
},
FinishReason: "stop",
},
},
})
if err != nil {
log.Println("write:", err)
break
}
}
wsMutex.Lock()
delete(wsConnections, conn)
wsMutex.Unlock()
})
r.GET("/status", func(c *gin.Context) {
stats := scraper.GetStats()
c.JSON(http.StatusOK, stats)
})
r.GET("/results", func(c *gin.Context) {
scraper.mutex.RLock()
defer scraper.mutex.RUnlock()
c.JSON(http.StatusOK, gin.H{"data": scraper.scrapedData, "count": len(scraper.scrapedData)})
})
log.Println("Starting server on :8080")
r.Run(":8080")
}

func loadConfig() ScraperConfig {
config := ScraperConfig{
Headless:             true,
MaxConcurrency:       4,
RetryAttempts:        3,
DelayBetweenRequests: 2000 * time.Millisecond,
UserAgents: []string{
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
},
EnableCloudflare: true,
EnableStealth:    true,
OpenAIKey:        os.Getenv("OPENAI_API_KEY"),
DataDir:          "./data",
LogDir:           "./logs",
}
if os.Getenv("HEADLESS") == "false" {
config.Headless = false
}
if concurrency := os.Getenv("MAX_CONCURRENCY"); concurrency != "" {
if c, err := strconv.Atoi(concurrency); err == nil {
config.MaxConcurrency = c
}
}
if retries := os.Getenv("RETRY_ATTEMPTS"); retries != "" {
if r, err := strconv.Atoi(retries); err == nil {
config.RetryAttempts = r
}
}
if delay := os.Getenv("DELAY_BETWEEN_REQUESTS"); delay != "" {
if d, err := strconv.Atoi(delay); err == nil {
config.DelayBetweenRequests = time.Duration(d) * time.Millisecond
}
}
if proxyURL := os.Getenv("PROXY_URL"); proxyURL != "" {
config.ProxyURL = proxyURL
}
if dataDir := os.Getenv("DATA_DIR"); dataDir != "" {
config.DataDir = dataDir
}
if logDir := os.Getenv("LOG_DIR"); logDir != "" {
config.LogDir = logDir
}
return config
}

func createDirectories(config ScraperConfig) {
dirs := []string{config.DataDir, config.LogDir, "./src", "./bin"}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
log.Printf("Warning: Failed to create directory %s: %v", dir, err)
}
}
}

func NewSocialScraper(config ScraperConfig) *SocialScraper {
ctx, cancel := context.WithCancel(context.Background())
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
MaxIdleConns:    100,
IdleConnTimeout: 90 * time.Second,
}
if config.ProxyURL != "" {
proxyURL, _ := url.Parse(config.ProxyURL)
tr.Proxy = http.ProxyURL(proxyURL)
}
jar, _ := cookiejar.New(nil)
client := &http.Client{
Transport: tr,
Jar:       jar,
Timeout:   30 * time.Second,
}
var aiClient *openai.Client
if config.OpenAIKey != "" {
aiClient = openai.NewClient(config.OpenAIKey)
}
return &SocialScraper{
ctx:        ctx,
cancel:     cancel,
client:     client,
config:     config,
scrapedData: make([]map[string]interface{}, 0),
failedUrls:  make(map[string]bool),
aiClient:    aiClient,
taskQueue:   make(chan Task, 1000),
resultChan:  make(chan TaskResult, 1000),
workerCount: config.MaxConcurrency,
}
}

func (s *SocialScraper) Initialize() error {
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.ExecAllocatorOption(func(o *chromedp.ExecAllocatorOptions) {
o.NoSandbox = true
o.DisableGPU = true
o.DisableDevShmUsage = true
o.DisableExtensions = true
o.DisablePlugins = true
o.DisableImages = true
o.WindowSize = []int{1366, 768}
o.UserAgent = s.config.UserAgents[0]
o.Args = append(o.Args, []string{
"--disable-web-security",
"--disable-features=VizDisplayCompositor",
"--disable-extensions",
"--disable-plugins",
"--disable-images",
"--disable-javascript",
"--disable-remote-fonts",
"--disable-webgl",
"--disable-3d-apis",
"--disable-extensions-except=",
"--disable-plugins-discovery",
"--disable-pdf-extension",
"--disable-print-preview",
"--disable-background-timer-throttling",
"--disable-renderer-backgrounding",
"--disable-ipc-flooding-protection",
"--disable-background-networking",
"--disable-default-apps",
"--disable-hang-monitor",
"--disable-prompt-on-repost",
"--disable-sync",
"--disable-features=VizDisplayCompositor,TranslateUI,BlinkGenPropertyTrees",
"--enable-features=NetworkService,NetworkServiceInProcess",
"--force-color-profile=srgb",
"--disable-features=VizDisplayCompositor",
"--disable-features=WebRtcHideLocalIpsWithMdns",
"--disable-features=MediaSessionService",
"--disable-features=AutofillServerCommunication",
"--disable-features=InterestFeedContentSuggestions",
"--disable-features=M

Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +298 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Socialscraper Pro Data Ninja Edition
3
- emoji: 📚
4
- colorFrom: purple
5
- colorTo: purple
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: SocialScraper Pro - Data Ninja Edition 🕵️‍♂️
3
+ colorFrom: gray
4
+ colorTo: green
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,299 @@
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>SocialScraper Pro - Data Ninja Edition</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/feather-icons"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
12
+
13
+ body {
14
+ font-family: 'Space Grotesk', sans-serif;
15
+ overflow-x: hidden;
16
+ }
17
+
18
+ .vanta-bg {
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ z-index: -1;
25
+ }
26
+
27
+ .glass-card {
28
+ background: rgba(255, 255, 255, 0.1);
29
+ backdrop-filter: blur(10px);
30
+ -webkit-backdrop-filter: blur(10px);
31
+ border: 1px solid rgba(255, 255, 255, 0.2);
32
+ }
33
+
34
+ .gradient-text {
35
+ background: linear-gradient(90deg, #3b82f6, #8b5cf6);
36
+ -webkit-background-clip: text;
37
+ background-clip: text;
38
+ color: transparent;
39
+ }
40
+
41
+ .pulse-animation {
42
+ animation: pulse 2s infinite;
43
+ }
44
+
45
+ @keyframes pulse {
46
+ 0% { transform: scale(1); }
47
+ 50% { transform: scale(1.05); }
48
+ 100% { transform: scale(1); }
49
+ }
50
+ </style>
51
+ </head>
52
+ <body class="bg-gray-900 text-white">
53
+ <div id="vanta-bg" class="vanta-bg"></div>
54
+
55
+ <!-- Navigation -->
56
+ <nav class="container mx-auto px-6 py-4 flex justify-between items-center">
57
+ <div class="flex items-center space-x-2">
58
+ <i data-feather="activity" class="text-indigo-500"></i>
59
+ <span class="text-xl font-bold gradient-text">SocialScraper Pro</span>
60
+ </div>
61
+ <div class="hidden md:flex space-x-8">
62
+ <a href="#" class="hover:text-indigo-400 transition">Features</a>
63
+ <a href="#" class="hover:text-indigo-400 transition">Pricing</a>
64
+ <a href="#" class="hover:text-indigo-400 transition">Documentation</a>
65
+ <a href="#" class="hover:text-indigo-400 transition">Support</a>
66
+ </div>
67
+ <div class="flex items-center space-x-4">
68
+ <button class="px-4 py-2 rounded-full bg-indigo-600 hover:bg-indigo-700 transition">
69
+ Get Started
70
+ </button>
71
+ <button class="md:hidden">
72
+ <i data-feather="menu"></i>
73
+ </button>
74
+ </div>
75
+ </nav>
76
+
77
+ <!-- Hero Section -->
78
+ <section class="container mx-auto px-6 py-20 md:py-32">
79
+ <div class="flex flex-col md:flex-row items-center">
80
+ <div class="md:w-1/2 mb-12 md:mb-0">
81
+ <h1 class="text-4xl md:text-6xl font-bold mb-6">
82
+ <span class="gradient-text">Extract</span> Social Data <br>
83
+ Like a <span class="gradient-text">Ninja</span>
84
+ </h1>
85
+ <p class="text-xl text-gray-300 mb-8">
86
+ The most powerful social media scraping tool for researchers, marketers, and data scientists.
87
+ </p>
88
+ <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
89
+ <button class="px-8 py-3 rounded-full bg-indigo-600 hover:bg-indigo-700 transition flex items-center justify-center pulse-animation">
90
+ <i data-feather="download" class="mr-2"></i>
91
+ Download Now
92
+ </button>
93
+ <button class="px-8 py-3 rounded-full bg-gray-800 hover:bg-gray-700 transition flex items-center justify-center">
94
+ <i data-feather="play" class="mr-2"></i>
95
+ Watch Demo
96
+ </button>
97
+ </div>
98
+ </div>
99
+ <div class="md:w-1/2">
100
+ <div class="glass-card rounded-2xl p-2 shadow-2xl">
101
+ <div class="bg-gray-800 rounded-xl p-4">
102
+ <div class="flex space-x-2 mb-4">
103
+ <div class="w-3 h-3 rounded-full bg-red-500"></div>
104
+ <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
105
+ <div class="w-3 h-3 rounded-full bg-green-500"></div>
106
+ </div>
107
+ <div class="bg-gray-900 rounded-lg p-4 font-mono text-sm overflow-x-auto">
108
+ <span class="text-green-400">$</span> socialscraper --platform twitter --query "#datascience" --limit 1000<br>
109
+ <span class="text-gray-500">[INFO] Connecting to Twitter API...</span><br>
110
+ <span class="text-gray-500">[INFO] Scraping 1000 posts...</span><br>
111
+ <span class="text-green-500">[SUCCESS] Data saved to twitter_data.json</span>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ </section>
118
+
119
+ <!-- Features Section -->
120
+ <section class="container mx-auto px-6 py-20">
121
+ <div class="text-center mb-16">
122
+ <h2 class="text-3xl md:text-4xl font-bold mb-4">Powerful Features</h2>
123
+ <p class="text-xl text-gray-300 max-w-2xl mx-auto">
124
+ Everything you need to collect, analyze, and visualize social media data at scale.
125
+ </p>
126
+ </div>
127
+
128
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
129
+ <!-- Feature 1 -->
130
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
131
+ <div class="w-12 h-12 rounded-full bg-indigo-500 flex items-center justify-center mb-4">
132
+ <i data-feather="globe" class="text-white"></i>
133
+ </div>
134
+ <h3 class="text-xl font-bold mb-2">Multi-Platform Support</h3>
135
+ <p class="text-gray-300">
136
+ Collect data from Twitter, Instagram, Facebook, Reddit, and more with a single tool.
137
+ </p>
138
+ </div>
139
+
140
+ <!-- Feature 2 -->
141
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
142
+ <div class="w-12 h-12 rounded-full bg-purple-500 flex items-center justify-center mb-4">
143
+ <i data-feather="cpu" class="text-white"></i>
144
+ </div>
145
+ <h3 class="text-xl font-bold mb-2">AI-Powered Analysis</h3>
146
+ <p class="text-gray-300">
147
+ Built-in sentiment analysis, topic modeling, and trend detection.
148
+ </p>
149
+ </div>
150
+
151
+ <!-- Feature 3 -->
152
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
153
+ <div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center mb-4">
154
+ <i data-feather="database" class="text-white"></i>
155
+ </div>
156
+ <h3 class="text-xl font-bold mb-2">Data Export</h3>
157
+ <p class="text-gray-300">
158
+ Export to JSON, CSV, or directly to your database.
159
+ </p>
160
+ </div>
161
+
162
+ <!-- Feature 4 -->
163
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
164
+ <div class="w-12 h-12 rounded-full bg-green-500 flex items-center justify-center mb-4">
165
+ <i data-feather="shield" class="text-white"></i>
166
+ </div>
167
+ <h3 class="text-xl font-bold mb-2">Privacy Focused</h3>
168
+ <p class="text-gray-300">
169
+ Ethical scraping with rate limiting and respect for platform TOS.
170
+ </p>
171
+ </div>
172
+
173
+ <!-- Feature 5 -->
174
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
175
+ <div class="w-12 h-12 rounded-full bg-yellow-500 flex items-center justify-center mb-4">
176
+ <i data-feather="code" class="text-white"></i>
177
+ </div>
178
+ <h3 class="text-xl font-bold mb-2">Developer Friendly</h3>
179
+ <p class="text-gray-300">
180
+ Full API access and extensible plugin system.
181
+ </p>
182
+ </div>
183
+
184
+ <!-- Feature 6 -->
185
+ <div class="glass-card rounded-xl p-6 hover:shadow-lg transition">
186
+ <div class="w-12 h-12 rounded-full bg-red-500 flex items-center justify-center mb-4">
187
+ <i data-feather="bar-chart-2" class="text-white"></i>
188
+ </div>
189
+ <h3 class="text-xl font-bold mb-2">Visual Analytics</h3>
190
+ <p class="text-gray-300">
191
+ Beautiful dashboards to visualize your data insights.
192
+ </p>
193
+ </div>
194
+ </div>
195
+ </section>
196
+
197
+ <!-- CTA Section -->
198
+ <section class="container mx-auto px-6 py-20 text-center">
199
+ <div class="glass-card rounded-2xl p-8 md:p-12 max-w-4xl mx-auto">
200
+ <h2 class="text-3xl md:text-4xl font-bold mb-6">Ready to Become a Data Ninja?</h2>
201
+ <p class="text-xl text-gray-300 mb-8 max-w-2xl mx-auto">
202
+ Join thousands of researchers and marketers who trust SocialScraper Pro for their data needs.
203
+ </p>
204
+ <button class="px-8 py-4 rounded-full bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 transition text-lg font-bold">
205
+ Get Started for Free
206
+ </button>
207
+ </div>
208
+ </section>
209
+
210
+ <!-- Footer -->
211
+ <footer class="bg-gray-800 py-12">
212
+ <div class="container mx-auto px-6">
213
+ <div class="flex flex-col md:flex-row justify-between">
214
+ <div class="mb-8 md:mb-0">
215
+ <div class="flex items-center space-x-2 mb-4">
216
+ <i data-feather="activity" class="text-indigo-500"></i>
217
+ <span class="text-xl font-bold gradient-text">SocialScraper Pro</span>
218
+ </div>
219
+ <p class="text-gray-400 max-w-xs">
220
+ The most powerful social media scraping tool for professionals.
221
+ </p>
222
+ </div>
223
+
224
+ <div class="grid grid-cols-2 md:grid-cols-3 gap-8">
225
+ <div>
226
+ <h4 class="text-lg font-bold mb-4">Product</h4>
227
+ <ul class="space-y-2">
228
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Features</a></li>
229
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Pricing</a></li>
230
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Documentation</a></li>
231
+ </ul>
232
+ </div>
233
+
234
+ <div>
235
+ <h4 class="text-lg font-bold mb-4">Company</h4>
236
+ <ul class="space-y-2">
237
+ <li><a href="#" class="text-gray-400 hover:text-white transition">About</a></li>
238
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Careers</a></li>
239
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Contact</a></li>
240
+ </ul>
241
+ </div>
242
+
243
+ <div>
244
+ <h4 class="text-lg font-bold mb-4">Legal</h4>
245
+ <ul class="space-y-2">
246
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Privacy</a></li>
247
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Terms</a></li>
248
+ <li><a href="#" class="text-gray-400 hover:text-white transition">Compliance</a></li>
249
+ </ul>
250
+ </div>
251
+ </div>
252
+ </div>
253
+
254
+ <div class="border-t border-gray-700 mt-12 pt-8 flex flex-col md:flex-row justify-between items-center">
255
+ <p class="text-gray-400 mb-4 md:mb-0">
256
+ © 2023 SocialScraper Pro. All rights reserved.
257
+ </p>
258
+ <div class="flex space-x-6">
259
+ <a href="#" class="text-gray-400 hover:text-white transition">
260
+ <i data-feather="twitter"></i>
261
+ </a>
262
+ <a href="#" class="text-gray-400 hover:text-white transition">
263
+ <i data-feather="github"></i>
264
+ </a>
265
+ <a href="#" class="text-gray-400 hover:text-white transition">
266
+ <i data-feather="linkedin"></i>
267
+ </a>
268
+ </div>
269
+ </div>
270
+ </div>
271
+ </footer>
272
+
273
+ <script>
274
+ feather.replace();
275
+
276
+ // Initialize Vanta.js effect
277
+ VANTA.NET({
278
+ el: "#vanta-bg",
279
+ mouseControls: true,
280
+ touchControls: true,
281
+ gyroControls: false,
282
+ minHeight: 200.00,
283
+ minWidth: 200.00,
284
+ scale: 1.00,
285
+ scaleMobile: 1.00,
286
+ color: 0x3b82f6,
287
+ backgroundColor: 0x111827,
288
+ points: 12.00,
289
+ maxDistance: 22.00,
290
+ spacing: 18.00
291
+ });
292
+
293
+ // Simple animation for demo purposes
294
+ document.querySelectorAll('.glass-card').forEach((card, index) => {
295
+ card.style.transitionDelay = `${index * 0.1}s`;
296
+ });
297
+ </script>
298
+ </body>
299
  </html>