limitedonly41 commited on
Commit
16fb0f1
·
verified ·
1 Parent(s): bf6df9e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -301
app.py CHANGED
@@ -1,311 +1,54 @@
1
- import gradio as gr
2
  import os
3
- import json
4
- import plotly.graph_objects as go
5
- import plotly.express as px
6
- import pandas as pd
7
- from datetime import datetime
8
- from parser import SemRush
9
 
10
- # Get credentials from Hugging Face Secrets
11
- SEMRUSH_USER_ID = os.getenv("SEMRUSH_USER_ID")
12
- SEMRUSH_API_KEY = os.getenv("SEMRUSH_API_KEY")
13
 
14
- def format_number(num):
15
- """Format large numbers with commas and abbreviations."""
16
- if num >= 1000000000:
17
- return f"{num/1000000000:.1f}B"
18
- elif num >= 1000000:
19
- return f"{num/1000000:.1f}M"
20
- elif num >= 1000:
21
- return f"{num/1000:.1f}K"
22
- else:
23
- return f"{num:,}"
24
 
25
- def create_traffic_chart(data):
26
- """Create a line chart for organic traffic over time."""
27
- if not data or "error" in data:
28
- return None
29
-
30
- dates = []
31
- traffic = []
32
-
33
- for date_str, traffic_val in data.items():
34
- # Parse date
35
- try:
36
- date_obj = datetime.strptime(date_str, "%Y%m%d")
37
- dates.append(date_obj)
38
- traffic.append(traffic_val)
39
- except:
40
- continue
41
-
42
- if not dates:
43
- return None
44
-
45
- df = pd.DataFrame({'Date': dates, 'Traffic': traffic})
46
- df = df.sort_values('Date')
47
-
48
- fig = px.line(df, x='Date', y='Traffic',
49
- title='Organic Traffic Trend Over Time',
50
- labels={'Traffic': 'Organic Traffic', 'Date': 'Date'})
51
-
52
- fig.update_traces(line=dict(color='#1f77b4', width=3))
53
- fig.update_layout(
54
- xaxis_title="Date",
55
- yaxis_title="Organic Traffic",
56
- hovermode='x unified',
57
- template="plotly_white"
58
- )
59
-
60
- return fig
61
-
62
- def create_organic_chart(data):
63
- """Create a bar chart for top organic traffic by country."""
64
- if not data or "error" in data:
65
- return None
66
-
67
- # Filter and sort data
68
- filtered_data = {k: v for k, v in data.items() if v > 0}
69
- sorted_data = dict(sorted(filtered_data.items(), key=lambda x: x[1], reverse=True)[:15])
70
-
71
- if not sorted_data:
72
- return None
73
-
74
- countries = list(sorted_data.keys())
75
- traffic = list(sorted_data.values())
76
-
77
- fig = px.bar(x=traffic, y=countries, orientation='h',
78
- title='Top 15 Countries by Organic Traffic',
79
- labels={'x': 'Organic Traffic', 'y': 'Country/Database'})
80
-
81
- fig.update_layout(
82
- yaxis={'categoryorder': 'total ascending'},
83
- template="plotly_white",
84
- height=500
85
- )
86
-
87
- return fig
88
-
89
- def get_domain_overview(domain):
90
- """Get domain overview data from SemRush."""
91
  try:
92
- if not SEMRUSH_USER_ID or not SEMRUSH_API_KEY:
93
- return "❌ API credentials not found. Please set SEMRUSH_USER_ID and SEMRUSH_API_KEY in Secrets.", None
94
-
95
- semrush = SemRush(SEMRUSH_USER_ID, SEMRUSH_API_KEY, domain)
96
- overview = semrush.domainOverview()
97
-
98
- if "error" in overview:
99
- return f"❌ Error: {overview['error']}", None
100
-
101
- if not overview:
102
- return "📊 No domain overview data found.", None
103
-
104
- # Create chart
105
- chart = create_traffic_chart(overview)
106
-
107
- # Format text summary
108
- formatted_lines = []
109
- sorted_overview = dict(sorted(overview.items()))
110
-
111
- for date_str, traffic in sorted_overview.items():
112
- try:
113
- date_obj = datetime.strptime(date_str, "%Y%m%d")
114
- formatted_date = date_obj.strftime("%B %Y")
115
- formatted_traffic = format_number(traffic)
116
- formatted_lines.append(f"📅 **{formatted_date}**: {formatted_traffic} visitors")
117
- except:
118
- formatted_lines.append(f"📅 **{date_str}**: {format_number(traffic)} visitors")
119
-
120
- result = "📈 **ORGANIC TRAFFIC TREND**\n\n" + "\n".join(formatted_lines)
121
-
122
- return result, chart
123
-
124
- except Exception as e:
125
- return f"❌ Error: {str(e['message'])}", None
126
-
127
- def get_organic_summary(domain):
128
- """Get organic summary data from SemRush."""
129
- try:
130
- if not SEMRUSH_USER_ID or not SEMRUSH_API_KEY:
131
- return "❌ API credentials not found. Please set SEMRUSH_USER_ID and SEMRUSH_API_KEY in Secrets.", None
132
-
133
- semrush = SemRush(SEMRUSH_USER_ID, SEMRUSH_API_KEY, domain)
134
- summary = semrush.organicSummary()
135
-
136
- if "error" in summary:
137
- return f"❌ Error: {summary['error']}", None
138
-
139
- if not summary:
140
- return "📊 No organic summary data found.", None
141
-
142
- # Create chart
143
- chart = create_organic_chart(summary)
144
-
145
- # Format text summary - show top 20 countries
146
- filtered_summary = {k: v for k, v in summary.items() if v > 0}
147
- sorted_summary = dict(sorted(filtered_summary.items(), key=lambda x: x[1], reverse=True)[:20])
148
-
149
- total_traffic = sum(sorted_summary.values())
150
-
151
- formatted_lines = [f"🌍 **TOTAL ORGANIC TRAFFIC**: {format_number(total_traffic)} visitors\n"]
152
-
153
- for i, (database, traffic) in enumerate(sorted_summary.items(), 1):
154
- percentage = (traffic / total_traffic) * 100 if total_traffic > 0 else 0
155
- flag_emoji = "🏆" if i <= 3 else "🌐"
156
- formatted_lines.append(f"{flag_emoji} **{database.upper()}**: {format_number(traffic)} ({percentage:.1f}%)")
157
-
158
- result = "\n".join(formatted_lines)
159
-
160
- return result, chart
161
-
162
- except Exception as e:
163
- return f"❌ Error: {str(e['message'])}", None
164
-
165
- def get_backlinks_summary(domain):
166
- """Get backlinks summary data from SemRush."""
167
- try:
168
- if not SEMRUSH_USER_ID or not SEMRUSH_API_KEY:
169
- return "❌ API credentials not found. Please set SEMRUSH_USER_ID and SEMRUSH_API_KEY in Secrets."
170
-
171
- semrush = SemRush(SEMRUSH_USER_ID, SEMRUSH_API_KEY, domain)
172
- backlinks = semrush.backlinksSummary()
173
-
174
- if "error" in backlinks:
175
- return f"❌ Error: {backlinks['error']}"
176
-
177
- if not backlinks:
178
- return "📊 No backlinks data found."
179
-
180
- # Format backlinks data nicely
181
- authority_score = backlinks.get('authorityScore', 0)
182
- total_backlinks = backlinks.get('backlinks', 0)
183
- health_score = backlinks.get('health', 0)
184
- link_power = backlinks.get('linkPower', 0)
185
- naturalness = backlinks.get('naturalness', 0)
186
- referring_domains = backlinks.get('referringDomains', 0)
187
- search_traffic = backlinks.get('searchTraffic', 0)
188
-
189
- # Authority score interpretation
190
- if authority_score >= 80:
191
- authority_status = "🟢 Excellent"
192
- elif authority_score >= 60:
193
- authority_status = "🟡 Good"
194
- elif authority_score >= 40:
195
- authority_status = "🟠 Average"
196
- else:
197
- authority_status = "🔴 Poor"
198
 
199
- # Health score interpretation
200
- if health_score >= 80:
201
- health_status = "🟢 Healthy"
202
- elif health_score >= 60:
203
- health_status = "🟡 Moderate"
204
- elif health_score >= 40:
205
- health_status = "🟠 Needs Attention"
 
 
 
 
 
 
 
 
 
 
206
  else:
207
- health_status = "🔴 Unhealthy"
208
-
209
- result = f"""🔗 **BACKLINKS PROFILE SUMMARY**
210
-
211
- 🏆 **Authority Score**: {authority_score}/100 ({authority_status})
212
- 📊 **Health Score**: {health_score}/100 ({health_status})
213
-
214
- 📈 **KEY METRICS**:
215
- • **Total Backlinks**: {format_number(total_backlinks)}
216
- • **Referring Domains**: {format_number(referring_domains)}
217
- • **Link Power**: {link_power}/10
218
- • **Naturalness**: {naturalness}/10
219
- • **Search Traffic**: {search_traffic}%
220
-
221
- 💡 **INSIGHTS**:
222
- • Average of {total_backlinks/referring_domains:.1f} links per referring domain
223
- • {"Strong" if link_power >= 5 else "Moderate" if link_power >= 3 else "Weak"} link profile strength
224
- • {"Natural" if naturalness >= 7 else "Moderately natural" if naturalness >= 5 else "Potentially artificial"} link pattern"""
225
-
226
- return result
227
-
228
  except Exception as e:
229
- return f"Error: {str(e['message'])}", None
230
-
231
- # Create Gradio interface with tabs
232
- with gr.Blocks(title="SemRush Domain Analyzer", theme=gr.themes.Soft()) as demo:
233
- gr.Markdown("# 🔍 SemRush Domain Analyzer")
234
- gr.Markdown("**Comprehensive SEO analysis powered by SemRush API**")
235
-
236
- with gr.Row():
237
- domain_input = gr.Textbox(
238
- label="🌐 Domain Name",
239
- placeholder="example.com or https://example.com",
240
- value="",
241
- scale=3
242
- )
243
- analyze_btn = gr.Button("🚀 Analyze Domain", variant="primary", scale=1)
244
-
245
- with gr.Tabs():
246
- with gr.Tab("📈 Traffic Overview"):
247
- with gr.Row():
248
- with gr.Column(scale=1):
249
- overview_output = gr.Markdown(
250
- value="Enter a domain and click 'Analyze Domain' to see traffic trends.",
251
- line_breaks=True
252
- )
253
- with gr.Column(scale=1):
254
- overview_chart = gr.Plot(label="Traffic Trend Chart")
255
-
256
- with gr.Tab("🌍 Geographic Distribution"):
257
- with gr.Row():
258
- with gr.Column(scale=1):
259
- organic_output = gr.Markdown(
260
- value="Geographic breakdown of organic traffic will appear here.",
261
- line_breaks=True
262
- )
263
- with gr.Column(scale=1):
264
- organic_chart = gr.Plot(label="Top Countries Chart")
265
-
266
- with gr.Tab("🔗 Backlinks Profile"):
267
- backlinks_output = gr.Markdown(
268
- value="Comprehensive backlinks analysis will appear here.",
269
- line_breaks=True
270
- )
271
-
272
- # Event handlers
273
- def analyze_domain(domain):
274
- if not domain:
275
- return (
276
- "⚠️ Please enter a domain name",
277
- None,
278
- "⚠️ Please enter a domain name",
279
- None,
280
- "⚠️ Please enter a domain name"
281
- )
282
-
283
- # Clean domain
284
- clean_domain = domain.replace('https://', '').replace('http://', '').strip('/')
285
-
286
- # Get all data
287
- overview_text, overview_fig = get_domain_overview(clean_domain)
288
- organic_text, organic_fig = get_organic_summary(clean_domain)
289
- backlinks_text = get_backlinks_summary(clean_domain)
290
-
291
- return overview_text, overview_fig, organic_text, organic_fig, backlinks_text
292
-
293
- analyze_btn.click(
294
- fn=analyze_domain,
295
- inputs=domain_input,
296
- outputs=[overview_output, overview_chart, organic_output, organic_chart, backlinks_output]
297
- )
298
-
299
- # Add examples
300
- gr.Examples(
301
- examples=[
302
- ["google.com"],
303
- ["github.com"],
304
- ["stackoverflow.com"],
305
- ["wikipedia.org"]
306
- ],
307
- inputs=domain_input
308
- )
309
 
310
  if __name__ == "__main__":
311
- demo.launch()
 
 
1
  import os
2
+ from huggingface_hub import hf_hub_download
3
+ import importlib.util
4
+ import sys
 
 
 
5
 
6
+ # Get HF token from environment (set in Space secrets)
7
+ HF_TOKEN = os.environ.get("HF_TOKEN")
 
8
 
9
+ # Your private model/repo details
10
+ REPO_ID = "limitedonly41/cv_all_src"
11
+ FILENAME = "semrush_scraper_code.py"
 
 
 
 
 
 
 
12
 
13
+ def load_and_run():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  try:
15
+ # Download the code file from private repo
16
+ file_path = hf_hub_download(
17
+ repo_id=REPO_ID,
18
+ filename=FILENAME,
19
+ token=HF_TOKEN,
20
+ repo_type="model"
21
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # Load the module dynamically
24
+ spec = importlib.util.spec_from_file_location("semrush_scraper_module", file_path)
25
+ module = importlib.util.module_from_spec(spec)
26
+ sys.modules["semrush_scraper_module"] = module
27
+ spec.loader.exec_module(module)
28
+
29
+ # Try to find and launch the interface
30
+ if hasattr(module, 'interface'):
31
+ print("Found 'interface' object, launching...")
32
+ module.interface.launch()
33
+ elif hasattr(module, 'demo'):
34
+ print("Found 'demo' object, launching...")
35
+ module.demo.launch()
36
+ elif hasattr(module, 'create_interface'):
37
+ print("Found 'create_interface' function, creating and launching...")
38
+ interface = module.create_interface()
39
+ interface.launch()
40
  else:
41
+ print("Error: Could not find 'interface', 'demo', or 'create_interface' in the loaded module")
42
+ print("Available attributes:", dir(module))
43
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  except Exception as e:
45
+ print(f"Error loading code: {e}")
46
+ import traceback
47
+ traceback.print_exc()
48
+ print("\nMake sure:")
49
+ print("1. HF_TOKEN is set in Space secrets")
50
+ print("2. REPO_ID points to your private repository")
51
+ print("3. The code file exists in the repository")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  if __name__ == "__main__":
54
+ load_and_run()