prince1604 commited on
Commit
3176f9b
·
1 Parent(s): 3c07190

Improve URL normalization logic and add API docs

Browse files
Files changed (3) hide show
  1. API_DOCUMENTATION.md +136 -0
  2. requirements.txt +0 -0
  3. src/crawler.py +11 -3
API_DOCUMENTATION.md ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Antigravity SEO Scaler - API Documentation
2
+
3
+ Base URL: `http://localhost:7860` (or your deployed URL)
4
+
5
+ ## 1. Start a New Scan
6
+ Initiates an asynchronous crawling and analysis job for a target domain.
7
+
8
+ - **Endpoint**: `/api/scanstart`
9
+ - **Method**: `POST`
10
+ - **Headers**: `Content-Type: application/json`
11
+ - **Body Parameters**:
12
+ - `domain` (string, required): The URL of the website to scan (e.g., "https://example.com").
13
+ - `limit` (integer, optional): Maximum number of pages to crawl. Default is `25`.
14
+
15
+ **Example Request (curl):**
16
+ ```bash
17
+ curl -X POST "http://localhost:7860/api/scanstart" \
18
+ -H "Content-Type: application/json" \
19
+ -d '{"domain": "https://example.com", "limit": 50}'
20
+ ```
21
+
22
+ **Example Response:**
23
+ ```json
24
+ {
25
+ "job_id": "8e8c40c5-77e0-4ad6-906a-53d038cd9fe7"
26
+ }
27
+ ```
28
+
29
+ ---
30
+
31
+ ## 2. Check Scan Progress
32
+ Retrieves the real-time status of a running job. You can use either a path parameter or a query parameter.
33
+
34
+ ### Option A: Path Parameter
35
+ - **Endpoint**: `/api/progress/{job_id}`
36
+ - **Method**: `GET`
37
+
38
+ ### Option B: Query Parameter
39
+ - **Endpoint**: `/api/progress`
40
+ - **Method**: `GET`
41
+ - **Query Parameters**:
42
+ - `job_id` (string, required): The ID returned by the start endpoint.
43
+
44
+ **Example Request:**
45
+ ```bash
46
+ curl "http://localhost:7860/api/progress/8e8c40c5-77e0-4ad6-906a-53d038cd9fe7"
47
+ # OR
48
+ curl "http://localhost:7860/api/progress?job_id=8e8c40c5-77e0-4ad6-906a-53d038cd9fe7"
49
+ ```
50
+
51
+ **Example Response:**
52
+ ```json
53
+ {
54
+ "status": "running",
55
+ "percent": 45,
56
+ "pages_scanned": 12,
57
+ "images_found": 86,
58
+ "message": "Scanning: https://example.com/about",
59
+ "elapsed_seconds": 15,
60
+ "eta_seconds": 20,
61
+ "error": null
62
+ }
63
+ ```
64
+ *Possible Statuses*: `pending`, `running`, `done`, `error`
65
+
66
+ ---
67
+
68
+ ## 3. Get Scan Results
69
+ Retrieves the final detailed JSON report. This should be called when the progress status is `done`.
70
+
71
+ ### Option A: Path Parameter
72
+ - **Endpoint**: `/api/result/{job_id}`
73
+ - **Method**: `GET`
74
+
75
+ ### Option B: Query Parameter
76
+ - **Endpoint**: `/api/result`
77
+ - **Method**: `GET`
78
+ - **Query Parameters**:
79
+ - `job_id` (string, required): The ID of the completed job.
80
+
81
+ **Example Request:**
82
+ ```bash
83
+ curl "http://localhost:7860/api/result/8e8c40c5-77e0-4ad6-906a-53d038cd9fe7"
84
+ ```
85
+
86
+ **Example Response:**
87
+ ```json
88
+ {
89
+ "summary": {
90
+ "total_pages_scanned": 50,
91
+ "total_images_found": 320,
92
+ "total_images_missing_alt": 45,
93
+ "blocked_reason": null,
94
+ "crawl_blocked": false
95
+ },
96
+ "details": [
97
+ {
98
+ "page_url": "https://example.com",
99
+ "images": [ ... ]
100
+ }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 4. System Status
108
+ Checks the health and resource usage of the underlying server.
109
+
110
+ - **Endpoint**: `/api/status`
111
+ - **Method**: `GET`
112
+ - **Query Parameters**:
113
+ - `domain` (string, optional): A target URL to check reachability for.
114
+
115
+ **Example Response:**
116
+ ```json
117
+ {
118
+ "cpu_percent": 12.5,
119
+ "memory_percent": 45.2,
120
+ "disk_usage": 60.1,
121
+ "target_reachable": true
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 5. Health Check
128
+ Simple endpoint for load balancers or uptime monitors.
129
+
130
+ - **Endpoint**: `/health`
131
+ - **Method**: `GET`
132
+
133
+ **Example Response:**
134
+ ```json
135
+ { "status": "alive" }
136
+ ```
requirements.txt CHANGED
Binary files a/requirements.txt and b/requirements.txt differ
 
src/crawler.py CHANGED
@@ -406,10 +406,17 @@ class Crawler:
406
  for href in raw_links:
407
  full_url = urljoin(url, href)
408
  parsed_url = urlparse(full_url)
409
- full_url = parsed_url._replace(fragment="").geturl()
 
 
410
  link_domain = parsed_url.netloc
411
 
412
- is_internal = link_domain == start_domain or link_domain.endswith('.' + base_domain) or link_domain == base_domain
 
 
 
 
 
413
 
414
  if is_internal:
415
  path = parsed_url.path.lower()
@@ -419,7 +426,8 @@ class Crawler:
419
  links_stats["skipped"] += 1
420
  continue
421
 
422
- exclude_keywords = ['/account', '/login', '/signin', '/signup', '/cart', '/checkout', '/wishlist', '/auth', 'javascript:', 'mailto:']
 
423
  if any(k in full_url.lower() for k in exclude_keywords):
424
  links_stats["skipped"] += 1
425
  continue
 
406
  for href in raw_links:
407
  full_url = urljoin(url, href)
408
  parsed_url = urlparse(full_url)
409
+ # Normalize: Remove fragment, strip trailing slash to avoid duplicates (/about vs /about/)
410
+ full_url = parsed_url._replace(fragment="").geturl().rstrip('/')
411
+
412
  link_domain = parsed_url.netloc
413
 
414
+ # Internal Check: Match base domain (handles www/non-www and subdomains)
415
+ is_internal = (
416
+ link_domain == start_domain or
417
+ link_domain.endswith('.' + base_domain) or
418
+ link_domain == base_domain
419
+ )
420
 
421
  if is_internal:
422
  path = parsed_url.path.lower()
 
426
  links_stats["skipped"] += 1
427
  continue
428
 
429
+ # Filter out non-content paths
430
+ exclude_keywords = ['/account', '/login', '/signin', '/signup', '/cart', '/checkout', '/wishlist', '/auth', 'javascript:', 'mailto:', 'tel:']
431
  if any(k in full_url.lower() for k in exclude_keywords):
432
  links_stats["skipped"] += 1
433
  continue