Spaces:
Running on Zero
Running on Zero
Update seo_analyzer.py
Browse files- seo_analyzer.py +0 -273
seo_analyzer.py
CHANGED
|
@@ -1127,279 +1127,6 @@ def calculate_seo_score(page):
|
|
| 1127 |
|
| 1128 |
return min(score, max_score)
|
| 1129 |
|
| 1130 |
-
# def calculate_seo_score(page):
|
| 1131 |
-
# """Calculate comprehensive SEO score"""
|
| 1132 |
-
# score = 0
|
| 1133 |
-
# max_score = 100
|
| 1134 |
-
|
| 1135 |
-
# # ===== TITLE OPTIMIZATION (10 points) =====
|
| 1136 |
-
# title = page.get('title', '')
|
| 1137 |
-
# if title:
|
| 1138 |
-
# title_len = len(title)
|
| 1139 |
-
# if 50 <= title_len <= 60: # Perfect
|
| 1140 |
-
# score += 10
|
| 1141 |
-
# elif 45 <= title_len <= 65: # Good
|
| 1142 |
-
# score += 8
|
| 1143 |
-
# elif 30 <= title_len <= 70: # Acceptable
|
| 1144 |
-
# score += 6
|
| 1145 |
-
# elif title_len > 0: # Exists but poor
|
| 1146 |
-
# score += 3
|
| 1147 |
-
|
| 1148 |
-
# # ===== META DESCRIPTION (8 points) =====
|
| 1149 |
-
# meta_desc = page.get('meta_description', '')
|
| 1150 |
-
# if meta_desc:
|
| 1151 |
-
# meta_len = len(meta_desc)
|
| 1152 |
-
# if 120 <= meta_len <= 155: # Perfect
|
| 1153 |
-
# score += 8
|
| 1154 |
-
# elif 100 <= meta_len <= 160: # Good
|
| 1155 |
-
# score += 6
|
| 1156 |
-
# elif 70 <= meta_len <= 170: # Acceptable
|
| 1157 |
-
# score += 4
|
| 1158 |
-
# elif meta_len > 0: # Exists but poor
|
| 1159 |
-
# score += 2
|
| 1160 |
-
|
| 1161 |
-
# # ===== HEADING STRUCTURE (12 points) =====
|
| 1162 |
-
# h1_count = page.get('h1_count', 0)
|
| 1163 |
-
# heading_order = page.get('heading_order', '')
|
| 1164 |
-
|
| 1165 |
-
# # H1 Score (6 points)
|
| 1166 |
-
# if h1_count == 1: # Perfect
|
| 1167 |
-
# score += 6
|
| 1168 |
-
# elif h1_count == 0: # Critical
|
| 1169 |
-
# score += 0
|
| 1170 |
-
# elif h1_count == 2: # Minor issue
|
| 1171 |
-
# score += 4
|
| 1172 |
-
# else: # Multiple H1s
|
| 1173 |
-
# score += 1
|
| 1174 |
-
|
| 1175 |
-
# # Heading Hierarchy (6 points)
|
| 1176 |
-
# if heading_order:
|
| 1177 |
-
# headings = [h.strip() for h in heading_order.split(',')]
|
| 1178 |
-
# heading_levels = []
|
| 1179 |
-
|
| 1180 |
-
# for heading in headings:
|
| 1181 |
-
# if heading.startswith('h'):
|
| 1182 |
-
# try:
|
| 1183 |
-
# level = int(heading[1])
|
| 1184 |
-
# heading_levels.append(level)
|
| 1185 |
-
# except:
|
| 1186 |
-
# continue
|
| 1187 |
-
|
| 1188 |
-
# if len(heading_levels) >= 3:
|
| 1189 |
-
# has_h1 = 1 in heading_levels
|
| 1190 |
-
# has_h2 = 2 in heading_levels
|
| 1191 |
-
# has_multiple_levels = len(set(heading_levels)) >= 2
|
| 1192 |
-
|
| 1193 |
-
# if has_h1 and has_h2 and has_multiple_levels:
|
| 1194 |
-
# score += 6
|
| 1195 |
-
# elif has_h1 and has_multiple_levels:
|
| 1196 |
-
# score += 4
|
| 1197 |
-
# elif has_h1:
|
| 1198 |
-
# score += 2
|
| 1199 |
-
# elif len(heading_levels) >= 1:
|
| 1200 |
-
# score += 2
|
| 1201 |
-
|
| 1202 |
-
# # ===== IMAGE OPTIMIZATION (15 points) =====
|
| 1203 |
-
# total_images = page.get('total_images', 0)
|
| 1204 |
-
# missing_alt_tags = page.get('missing_alt_tags', 0)
|
| 1205 |
-
# small_images = page.get('small_images', 0)
|
| 1206 |
-
# large_images = page.get('large_images', 0)
|
| 1207 |
-
# ideal_images = page.get('ideal_images', 0)
|
| 1208 |
-
|
| 1209 |
-
# # Alt Text Score (5 points)
|
| 1210 |
-
# if total_images == 0:
|
| 1211 |
-
# score += 5
|
| 1212 |
-
# else:
|
| 1213 |
-
# alt_ratio = (total_images - missing_alt_tags) / total_images
|
| 1214 |
-
# if alt_ratio >= 0.95:
|
| 1215 |
-
# score += 5
|
| 1216 |
-
# elif alt_ratio >= 0.80:
|
| 1217 |
-
# score += 4
|
| 1218 |
-
# elif alt_ratio >= 0.60:
|
| 1219 |
-
# score += 3
|
| 1220 |
-
# elif alt_ratio >= 0.40:
|
| 1221 |
-
# score += 2
|
| 1222 |
-
# elif alt_ratio > 0:
|
| 1223 |
-
# score += 1
|
| 1224 |
-
|
| 1225 |
-
# # Image Size Optimization (5 points)
|
| 1226 |
-
# if total_images > 0:
|
| 1227 |
-
# ideal_ratio = ideal_images / total_images
|
| 1228 |
-
# if ideal_ratio >= 0.8:
|
| 1229 |
-
# score += 5
|
| 1230 |
-
# elif ideal_ratio >= 0.6:
|
| 1231 |
-
# score += 4
|
| 1232 |
-
# elif ideal_ratio >= 0.4:
|
| 1233 |
-
# score += 3
|
| 1234 |
-
# elif ideal_ratio >= 0.2:
|
| 1235 |
-
# score += 2
|
| 1236 |
-
# else:
|
| 1237 |
-
# score += 1
|
| 1238 |
-
# else:
|
| 1239 |
-
# score += 5
|
| 1240 |
-
|
| 1241 |
-
# # Image Quantity (5 points)
|
| 1242 |
-
# if total_images == 0:
|
| 1243 |
-
# score += 3
|
| 1244 |
-
# elif 3 <= total_images <= 20:
|
| 1245 |
-
# score += 5
|
| 1246 |
-
# elif total_images <= 50:
|
| 1247 |
-
# score += 4
|
| 1248 |
-
# elif total_images <= 100:
|
| 1249 |
-
# score += 3
|
| 1250 |
-
# else:
|
| 1251 |
-
# score += 2
|
| 1252 |
-
|
| 1253 |
-
# # ===== LINK STRUCTURE (10 points) =====
|
| 1254 |
-
# internal_links = page.get('internal_links', 0)
|
| 1255 |
-
# external_links = page.get('external_links', 0)
|
| 1256 |
-
|
| 1257 |
-
# # Internal Links (6 points)
|
| 1258 |
-
# if internal_links >= 80:
|
| 1259 |
-
# score += 6
|
| 1260 |
-
# elif internal_links >= 60:
|
| 1261 |
-
# score += 5
|
| 1262 |
-
# elif internal_links >= 40:
|
| 1263 |
-
# score += 4
|
| 1264 |
-
# elif internal_links >= 20:
|
| 1265 |
-
# score += 3
|
| 1266 |
-
# elif internal_links >= 10:
|
| 1267 |
-
# score += 2
|
| 1268 |
-
|
| 1269 |
-
# # External Links (4 points)
|
| 1270 |
-
# if external_links >= 10:
|
| 1271 |
-
# score += 4
|
| 1272 |
-
# elif external_links >= 7:
|
| 1273 |
-
# score += 3
|
| 1274 |
-
# elif external_links >= 4:
|
| 1275 |
-
# score += 2
|
| 1276 |
-
|
| 1277 |
-
# # ===== TECHNICAL SEO (20 points) =====
|
| 1278 |
-
# # Canonical Tag (3 points)
|
| 1279 |
-
# if page.get('canonical_tag', False):
|
| 1280 |
-
# score += 3
|
| 1281 |
-
|
| 1282 |
-
# # Robots Meta (3 points)
|
| 1283 |
-
# robots_meta = page.get('robots_meta', '')
|
| 1284 |
-
# if robots_meta:
|
| 1285 |
-
# robots_lower = robots_meta.lower()
|
| 1286 |
-
# if 'noindex' not in robots_lower and 'nofollow' not in robots_lower:
|
| 1287 |
-
# score += 3
|
| 1288 |
-
# elif 'noindex' in robots_lower:
|
| 1289 |
-
# score += 0
|
| 1290 |
-
# else:
|
| 1291 |
-
# score += 2
|
| 1292 |
-
# else:
|
| 1293 |
-
# score += 2
|
| 1294 |
-
|
| 1295 |
-
# # Viewport (3 points)
|
| 1296 |
-
# if page.get('viewport_present', False):
|
| 1297 |
-
# score += 3
|
| 1298 |
-
|
| 1299 |
-
# # Schema Markup (4 points)
|
| 1300 |
-
# schema_types = page.get('schema_types', '')
|
| 1301 |
-
# if schema_types and schema_types.strip() and schema_types != "No schema found":
|
| 1302 |
-
# schema_count = len([s for s in schema_types.split(', ') if s.strip()])
|
| 1303 |
-
# if schema_count >= 3:
|
| 1304 |
-
# score += 4
|
| 1305 |
-
# elif schema_count >= 2:
|
| 1306 |
-
# score += 3
|
| 1307 |
-
# elif schema_count == 1:
|
| 1308 |
-
# score += 2
|
| 1309 |
-
|
| 1310 |
-
# # OpenGraph Tags (4 points)
|
| 1311 |
-
# opengraph_tags = page.get('opengraph_tags', 0)
|
| 1312 |
-
# if opengraph_tags >= 10:
|
| 1313 |
-
# score += 4
|
| 1314 |
-
# elif opengraph_tags >= 7:
|
| 1315 |
-
# score += 3
|
| 1316 |
-
# elif opengraph_tags >= 5:
|
| 1317 |
-
# score += 2
|
| 1318 |
-
# elif opengraph_tags >= 3:
|
| 1319 |
-
# score += 1
|
| 1320 |
-
|
| 1321 |
-
# # Twitter Cards (3 points)
|
| 1322 |
-
# twitter_tags = page.get('twitter_tags', 0)
|
| 1323 |
-
# if twitter_tags >= 5:
|
| 1324 |
-
# score += 3
|
| 1325 |
-
# elif twitter_tags >= 3:
|
| 1326 |
-
# score += 2
|
| 1327 |
-
# elif twitter_tags >= 1:
|
| 1328 |
-
# score += 1
|
| 1329 |
-
|
| 1330 |
-
# # ===== CONTENT QUALITY (25 points) =====
|
| 1331 |
-
# word_count = page.get('word_count', 0)
|
| 1332 |
-
# readability_score = page.get('readability_score', 0)
|
| 1333 |
-
# grammar_errors = page.get('grammar_errors', 0)
|
| 1334 |
-
# text_to_html_ratio = page.get('text_to_html_ratio', 0)
|
| 1335 |
-
# top_keywords = page.get('top_keywords', '')
|
| 1336 |
-
|
| 1337 |
-
# # Word Count (6 points)
|
| 1338 |
-
# if word_count >= 2000:
|
| 1339 |
-
# score += 6
|
| 1340 |
-
# elif word_count >= 1200:
|
| 1341 |
-
# score += 5
|
| 1342 |
-
# elif word_count >= 800:
|
| 1343 |
-
# score += 4
|
| 1344 |
-
# elif word_count >= 500:
|
| 1345 |
-
# score += 3
|
| 1346 |
-
# elif word_count >= 300:
|
| 1347 |
-
# score += 2
|
| 1348 |
-
# elif word_count >= 150:
|
| 1349 |
-
# score += 1
|
| 1350 |
-
|
| 1351 |
-
# # Readability (6 points)
|
| 1352 |
-
# if readability_score >= 50:
|
| 1353 |
-
# score += 6
|
| 1354 |
-
# elif readability_score >= 45:
|
| 1355 |
-
# score += 5
|
| 1356 |
-
# elif readability_score >= 40:
|
| 1357 |
-
# score += 4
|
| 1358 |
-
# elif readability_score >= 35:
|
| 1359 |
-
# score += 3
|
| 1360 |
-
# elif readability_score >= 20:
|
| 1361 |
-
# score += 2
|
| 1362 |
-
# elif readability_score >= 10:
|
| 1363 |
-
# score += 1
|
| 1364 |
-
|
| 1365 |
-
# # Grammar (4 points)
|
| 1366 |
-
# if grammar_errors == 0:
|
| 1367 |
-
# score += 4
|
| 1368 |
-
# elif grammar_errors <= 2:
|
| 1369 |
-
# score += 3
|
| 1370 |
-
# elif grammar_errors <= 5:
|
| 1371 |
-
# score += 2
|
| 1372 |
-
# elif grammar_errors <= 10:
|
| 1373 |
-
# score += 1
|
| 1374 |
-
|
| 1375 |
-
# # Text to HTML Ratio (5 points)
|
| 1376 |
-
# if text_to_html_ratio >= 25:
|
| 1377 |
-
# score += 5
|
| 1378 |
-
# elif text_to_html_ratio >= 20:
|
| 1379 |
-
# score += 4
|
| 1380 |
-
# elif text_to_html_ratio >= 15:
|
| 1381 |
-
# score += 3
|
| 1382 |
-
# elif text_to_html_ratio >= 10:
|
| 1383 |
-
# score += 2
|
| 1384 |
-
# elif text_to_html_ratio >= 5:
|
| 1385 |
-
# score += 1
|
| 1386 |
-
|
| 1387 |
-
# # Keyword Optimization (4 points)
|
| 1388 |
-
# if top_keywords:
|
| 1389 |
-
# keyword_entries = [k for k in top_keywords.split(', ') if ':' in k and float(k.split(':')[1][:-1]) > 1.0]
|
| 1390 |
-
# keyword_count = len(keyword_entries)
|
| 1391 |
-
|
| 1392 |
-
# if keyword_count >= 8:
|
| 1393 |
-
# score += 4
|
| 1394 |
-
# elif keyword_count >= 5:
|
| 1395 |
-
# score += 3
|
| 1396 |
-
# elif keyword_count >= 3:
|
| 1397 |
-
# score += 2
|
| 1398 |
-
# elif keyword_count >= 1:
|
| 1399 |
-
# score += 1
|
| 1400 |
-
|
| 1401 |
-
# return min(score, max_score)
|
| 1402 |
-
|
| 1403 |
# ==============================
|
| 1404 |
# ENHANCED MAIN FUNCTION WITH ULTRA-SPECIFIC AI SUGGESTIONS
|
| 1405 |
# ==============================
|
|
|
|
| 1127 |
|
| 1128 |
return min(score, max_score)
|
| 1129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1130 |
# ==============================
|
| 1131 |
# ENHANCED MAIN FUNCTION WITH ULTRA-SPECIFIC AI SUGGESTIONS
|
| 1132 |
# ==============================
|