Jay-2776 commited on
Commit
10e43ba
ยท
verified ยท
1 Parent(s): a92c739

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -87
app.py CHANGED
@@ -1,144 +1,180 @@
1
- import gradio as gr
2
- import requests
3
- import pandas as pd
4
  import time
5
  import os
 
 
 
6
  from urllib.parse import urlparse
7
 
8
- # ---------------- CONFIG ----------------
9
- API_KEY = os.getenv("HASDATA_API_KEY")
10
- BASE_URL = "https://api.hasdata.com/scrape/google/serp"
11
 
12
- TARGET_DOMAIN = "rishabhsoft.com"
13
- MAX_PAGES = 10 # Top 10 pages (Top 100 results)
14
 
15
- if not API_KEY:
16
- raise ValueError("HASDATA_API_KEY is not set in Hugging Face Secrets")
17
 
18
- # ---------------- CORE LOGIC ----------------
19
- def check_domain_rank(keyword):
20
- """
21
- Checks ranking of TARGET_DOMAIN for a keyword
22
- Uses HasData SERP API
23
- USA Google results only
24
- Stops once domain is found
25
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  headers = {
28
- "Accept": "application/json",
29
- "X-API-KEY": API_KEY
30
  }
31
 
32
  for page in range(MAX_PAGES):
 
 
33
  params = {
34
- "engine": "google",
35
  "q": keyword,
36
- "start": page * 10,
37
- "num": 10,
38
-
39
- # Force USA Google
40
- "gl": "us",
41
- "hl": "en",
42
- "location": "United States",
43
- "google_domain": "google.com"
44
  }
45
 
46
  response = requests.get(
47
- BASE_URL,
48
  headers=headers,
49
  params=params,
50
  timeout=30
51
  )
52
 
53
  if response.status_code != 200:
54
- return {
55
- "Keyword": keyword,
56
- "Domain": TARGET_DOMAIN,
57
- "Page": "Error",
58
- "Position on Page": "Error",
59
- "Absolute Rank": "Error",
60
- "URL": None,
61
- "Title": f"API Error {response.status_code}: {response.text}"
62
- }
63
 
64
  data = response.json()
65
- organic_results = data.get("organic_results", [])
66
 
67
- if not organic_results:
68
- break
 
 
 
69
 
70
- for idx, result in enumerate(organic_results, start=1):
71
- url = result.get("link", "")
72
- domain = urlparse(url).netloc.replace("www.", "")
 
73
 
74
- if TARGET_DOMAIN in domain:
75
- return {
 
 
76
  "Keyword": keyword,
77
- "Domain": TARGET_DOMAIN,
78
  "Page": page + 1,
79
  "Position on Page": idx,
80
- "Absolute Rank": page * 10 + idx,
81
  "URL": url,
82
- "Title": result.get("title")
83
- }
 
 
 
84
 
85
- time.sleep(1) # rate-limit safety
86
 
87
- return {
 
 
 
88
  "Keyword": keyword,
89
- "Domain": TARGET_DOMAIN,
90
  "Page": "Not Found",
91
  "Position on Page": "Not Found",
92
  "Absolute Rank": "Not Found",
93
  "URL": None,
94
- "Title": "Not ranking in Top 100"
95
- }
96
-
97
- # ---------------- BULK HANDLER ----------------
98
- def run_bulk_keywords(text):
99
- if not text.strip():
 
 
100
  return None, None
101
 
102
- keywords = [k.strip() for k in text.splitlines() if k.strip()]
103
- results = []
104
 
105
- for keyword in keywords:
106
- results.append(check_domain_rank(keyword))
107
 
108
- df = pd.DataFrame(results)
109
 
110
- output_file = "rishabhsoft_us_keyword_rankings.xlsx"
111
- df.to_excel(output_file, index=False)
112
 
113
- return df, output_file
114
 
115
- # ---------------- UI ----------------
116
- with gr.Blocks(title="Domain Rank Checker โ€” USA Google Results") as demo:
117
- gr.Markdown("## ๐Ÿ” Domain Rank Checker โ€” USA Google Results")
118
- gr.Markdown(
119
- "**Tracked domain:** https://www.rishabhsoft.com/\n\n"
120
- "- ๐Ÿ‡บ๐Ÿ‡ธ USA Google results only\n"
121
- "- ๐Ÿ”Ž Checks Top 10 pages (Top 100)\n"
122
- "- โšก Stops when domain is found (credit-optimized)\n"
123
- "- ๐Ÿ“‹ One keyword per line\n"
124
- "- ๐Ÿ“ฅ Excel export supported"
125
- )
126
 
127
- keyword_box = gr.Textbox(
128
- label="Keywords (one per line)",
129
- lines=10,
130
- placeholder=".NET MAUI app development services\nenterprise software development"
 
 
 
 
 
 
 
131
  )
132
 
133
  run_btn = gr.Button("Check Rankings")
134
 
135
- output_table = gr.Dataframe(wrap=True)
136
- download_file = gr.File(label="Download Excel Report")
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  run_btn.click(
139
- fn=run_bulk_keywords,
140
- inputs=keyword_box,
141
  outputs=[output_table, download_file]
142
  )
143
 
 
 
144
  demo.launch()
 
 
 
 
1
  import time
2
  import os
3
+ import requests
4
+ import pandas as pd
5
+ import gradio as gr
6
  from urllib.parse import urlparse
7
 
8
+ # =====================================================
9
+ # CONFIGURATION
10
+ # =====================================================
11
 
12
+ # ๐Ÿ” Hugging Face Secret
13
+ HASDATA_API_KEY = os.getenv("HASDATA_API_KEY")
14
 
15
+ HASDATA_ENDPOINT = "https://api.hasdata.com/scrape/google/serp"
 
16
 
17
+ TARGET_DOMAIN = "rishabhsoft.com"
18
+ COUNTRY = "us" # change to "in" for India
19
+ LANGUAGE = "en"
20
+ LOCATION = "United States" if COUNTRY == "us" else "India"
21
+
22
+ MAX_PAGES = 10 # Top 100
23
+ RESULTS_PER_PAGE = 10
24
+ SLEEP_TIME = 1
25
+
26
+ if not HASDATA_API_KEY:
27
+ raise RuntimeError("HASDATA_API_KEY not found. Add it in Hugging Face Secrets.")
28
+
29
+ # =====================================================
30
+ # HELPERS
31
+ # =====================================================
32
+ def normalize_domain(url: str) -> str:
33
+ try:
34
+ return urlparse(url).netloc.replace("www.", "").lower()
35
+ except Exception:
36
+ return ""
37
+
38
+ # =====================================================
39
+ # CORE RANK CHECK
40
+ # =====================================================
41
+ def check_domain_rank(keyword: str) -> pd.DataFrame:
42
+ keyword = keyword.strip()
43
+ results = []
44
 
45
  headers = {
46
+ "x-api-key": HASDATA_API_KEY
 
47
  }
48
 
49
  for page in range(MAX_PAGES):
50
+ start = page * RESULTS_PER_PAGE
51
+
52
  params = {
 
53
  "q": keyword,
54
+ "gl": COUNTRY,
55
+ "hl": LANGUAGE,
56
+ "domain": "google.com",
57
+ "location": LOCATION,
58
+ "start": start,
59
+ "num": RESULTS_PER_PAGE,
60
+ "deviceType": "desktop"
 
61
  }
62
 
63
  response = requests.get(
64
+ HASDATA_ENDPOINT,
65
  headers=headers,
66
  params=params,
67
  timeout=30
68
  )
69
 
70
  if response.status_code != 200:
71
+ print(f"API Error [{response.status_code}]: {response.text}")
72
+ break
 
 
 
 
 
 
 
73
 
74
  data = response.json()
 
75
 
76
+ organic_results = (
77
+ data.get("organic_results")
78
+ or data.get("organicResults")
79
+ or []
80
+ )
81
 
82
+ for idx, item in enumerate(organic_results, start=1):
83
+ url = item.get("link") or item.get("url") or ""
84
+ if not url:
85
+ continue
86
 
87
+ domain = normalize_domain(url)
88
+
89
+ if domain.endswith(TARGET_DOMAIN):
90
+ results.append({
91
  "Keyword": keyword,
92
+ "Domain": f"https://www.{TARGET_DOMAIN}/",
93
  "Page": page + 1,
94
  "Position on Page": idx,
95
+ "Absolute Rank": start + idx,
96
  "URL": url,
97
+ "Title": item.get("title")
98
+ })
99
+
100
+ if results:
101
+ break
102
 
103
+ time.sleep(SLEEP_TIME)
104
 
105
+ if results:
106
+ return pd.DataFrame(results)
107
+
108
+ return pd.DataFrame([{
109
  "Keyword": keyword,
110
+ "Domain": f"https://www.{TARGET_DOMAIN}/",
111
  "Page": "Not Found",
112
  "Position on Page": "Not Found",
113
  "Absolute Rank": "Not Found",
114
  "URL": None,
115
+ "Title": "Not ranking in top 100"
116
+ }])
117
+
118
+ # =====================================================
119
+ # BULK EXCEL HANDLER
120
+ # =====================================================
121
+ def run_bulk_excel(file):
122
+ if file is None:
123
  return None, None
124
 
125
+ df = pd.read_excel(file)
 
126
 
127
+ if "keyword" not in df.columns:
128
+ raise ValueError("Excel must contain a 'keyword' column")
129
 
130
+ all_results = []
131
 
132
+ for kw in df["keyword"].dropna().unique():
133
+ all_results.append(check_domain_rank(str(kw)))
134
 
135
+ final_df = pd.concat(all_results, ignore_index=True)
136
 
137
+ output_file = "hasdata_keyword_ranking.xlsx"
138
+ final_df.to_excel(output_file, index=False)
139
+
140
+ return final_df, output_file
 
 
 
 
 
 
 
141
 
142
+ # =====================================================
143
+ # GRADIO UI
144
+ # =====================================================
145
+ with gr.Blocks(title="Hasdata Google Rank Checker") as demo:
146
+ gr.Markdown("## ๐Ÿ” Google Keyword Rank Checker (Hasdata)")
147
+ gr.Markdown(f"**Target Domain:** https://www.{TARGET_DOMAIN}/")
148
+ gr.Markdown(f"**Country:** {COUNTRY.upper()} | **Device:** Desktop")
149
+
150
+ excel_input = gr.File(
151
+ label="Upload Excel (.xlsx) with 'keyword' column",
152
+ file_types=[".xlsx"]
153
  )
154
 
155
  run_btn = gr.Button("Check Rankings")
156
 
157
+ output_table = gr.Dataframe(
158
+ headers=[
159
+ "Keyword",
160
+ "Domain",
161
+ "Page",
162
+ "Position on Page",
163
+ "Absolute Rank",
164
+ "URL",
165
+ "Title"
166
+ ],
167
+ wrap=True
168
+ )
169
+
170
+ download_file = gr.File(label="Download Result Excel")
171
 
172
  run_btn.click(
173
+ fn=run_bulk_excel,
174
+ inputs=excel_input,
175
  outputs=[output_table, download_file]
176
  )
177
 
178
+ # ๐Ÿ”’ REQUIRED for Hugging Face + Python 3.12
179
+ demo.queue()
180
  demo.launch()