Mazenbs commited on
Commit
d883482
·
verified ·
1 Parent(s): 3eb1c56

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -14
app.py CHANGED
@@ -1,31 +1,128 @@
1
  from fastapi import FastAPI, HTTPException
2
- from pydantic import BaseModel, HttpUrl
3
- from typing import List, Dict
4
  import requests
5
  from helpers.text_blocks import extract_text_from_url
 
6
 
7
  app = FastAPI(
8
  title="Text Extractor API",
9
- description="API لاستخراج النصوص من صفحات الويب",
10
- version="1.0.0"
11
  )
12
 
13
  class URLRequest(BaseModel):
14
  url: HttpUrl
15
- timeout: int = 10
 
 
 
 
16
 
17
  class TextResponse(BaseModel):
18
  text: str
19
 
20
- @app.post("/extract", response_model=List[TextResponse])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  async def extract_text_endpoint(request: URLRequest):
22
  """
23
- استخراج النصوص من رابط صفحة ويب
 
 
 
 
24
  """
25
  try:
26
- # استدعاء دالة الاستخراج
27
- result = extract_text_from_url(str(request.url), request.timeout)
28
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  except requests.RequestException as e:
31
  raise HTTPException(
@@ -41,14 +138,46 @@ async def extract_text_endpoint(request: URLRequest):
41
  @app.get("/")
42
  async def root():
43
  return {
44
- "message": "Text Extractor API is running!",
45
- "endpoint": "/extract-text",
46
- "method": "POST"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
  @app.get("/health")
50
  async def health_check():
51
- return {"status": "healthy"}
 
 
 
 
 
 
 
 
52
 
53
  if __name__ == "__main__":
54
  import uvicorn
 
1
  from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel, HttpUrl, Field
3
+ from typing import List, Dict, Optional, Tuple
4
  import requests
5
  from helpers.text_blocks import extract_text_from_url
6
+ from helpers.output_clipper import clip_by_ranges
7
 
8
  app = FastAPI(
9
  title="Text Extractor API",
10
+ description="API لاستخراج النصوص من صفحات الويب مع إمكانية التحكم في النطاقات",
11
+ version="2.0.0"
12
  )
13
 
14
  class URLRequest(BaseModel):
15
  url: HttpUrl
16
+ timeout: int = Field(default=10, ge=1, le=60)
17
+ ranges: Optional[List[List[int]]] = Field(
18
+ default=None,
19
+ description="نطاقات الاستخراج في شكل [[start, end], [start, end]] - اختياري"
20
+ )
21
 
22
  class TextResponse(BaseModel):
23
  text: str
24
 
25
+ class CountResponse(BaseModel):
26
+ total_texts: int
27
+ url: str
28
+
29
+ def validate_ranges(ranges: List[List[int]]) -> List[Tuple[int, int]]:
30
+ """
31
+ التحقق من صحة النطاقات وتحويلها للتنسيق المطلوب
32
+
33
+ Args:
34
+ ranges: النطاقات في شكل [[start, end], ...]
35
+
36
+ Returns:
37
+ النطاقات المحولة [(start, end), ...]
38
+
39
+ Raises:
40
+ HTTPException: في حالة وجود نطاق غير صحيح
41
+ """
42
+ validated_ranges = []
43
+
44
+ for i, range_pair in enumerate(ranges):
45
+ if len(range_pair) != 2:
46
+ raise HTTPException(
47
+ status_code=400,
48
+ detail=f"النطاق رقم {i+1} غير صحيح. كل نطاق يجب أن يحتوي على عنصرين: [start, end]"
49
+ )
50
+
51
+ start, end = range_pair
52
+
53
+ if not isinstance(start, int) or not isinstance(end, int):
54
+ raise HTTPException(
55
+ status_code=400,
56
+ detail=f"النطاق رقم {i+1} غير صحيح. القيم يجب أن تكون أرقام صحيحة"
57
+ )
58
+
59
+ if start < 0:
60
+ raise HTTPException(
61
+ status_code=400,
62
+ detail=f"النطاق رقم {i+1} غير صحيح. البداية يجب أن تكون >= 0"
63
+ )
64
+
65
+ if end <= start:
66
+ raise HTTPException(
67
+ status_code=400,
68
+ detail=f"النطاق رقم {i+1} غير صحيح. النهاية يجب أن تكون أكبر من البداية"
69
+ )
70
+
71
+ validated_ranges.append((start, end))
72
+
73
+ return validated_ranges
74
+
75
+ @app.post("/extract-text", response_model=List[TextResponse])
76
  async def extract_text_endpoint(request: URLRequest):
77
  """
78
+ استخراج النصوص من رابط صفحة ويب مع إمكانية تحديد النطاقات
79
+
80
+ Examples:
81
+ - استخراج الكل: {"url": "https://example.com"}
82
+ - استخراج نطاقات محددة: {"url": "https://example.com", "ranges": [[0, 10], [20, 30]]}
83
  """
84
  try:
85
+ # استخراج جميع النصوص أولاً باستخدام المستخرج الأصلي
86
+ all_texts = extract_text_from_url(str(request.url), request.timeout)
87
+
88
+ # إذا لم يتم تحديد نطاقات، إرجاع جميع النصوص
89
+ if not request.ranges:
90
+ return all_texts
91
+
92
+ # التحقق من صحة النطاقات
93
+ validated_ranges = validate_ranges(request.ranges)
94
+
95
+ # تطبيق فلترة النطاقات باستخدام output_clipper
96
+ filtered_texts = clip_by_ranges(all_texts, validated_ranges)
97
+
98
+ return filtered_texts
99
+
100
+ except requests.RequestException as e:
101
+ raise HTTPException(
102
+ status_code=400,
103
+ detail=f"خطأ في جلب الصفحة: {str(e)}"
104
+ )
105
+ except HTTPException:
106
+ # إعادة إثارة أخطاء HTTP كما هي
107
+ raise
108
+ except Exception as e:
109
+ raise HTTPException(
110
+ status_code=500,
111
+ detail=f"خطأ في معالجة المحتوى: {str(e)}"
112
+ )
113
+
114
+ @app.post("/text-count", response_model=CountResponse)
115
+ async def get_text_count_endpoint(request: URLRequest):
116
+ """
117
+ الحصول على عدد النصوص الكلي في الصفحة
118
+ مفيد لمعرفة النطاقات المتاحة قبل الاستخراج
119
+ """
120
+ try:
121
+ # استخراج جميع النصوص للحصول على العدد
122
+ all_texts = extract_text_from_url(str(request.url), request.timeout)
123
+ count = len(all_texts)
124
+
125
+ return CountResponse(total_texts=count, url=str(request.url))
126
 
127
  except requests.RequestException as e:
128
  raise HTTPException(
 
138
  @app.get("/")
139
  async def root():
140
  return {
141
+ "message": "Text Extractor API v2.0 is running! 🔥",
142
+ "endpoints": {
143
+ "extract_text": "/extract-text (POST)",
144
+ "text_count": "/text-count (POST)",
145
+ "docs": "/docs",
146
+ "health": "/health"
147
+ },
148
+ "features": [
149
+ "استخراج جميع النصوص من صفحات الويب",
150
+ "استخراج نطاقات محددة",
151
+ "عد النصوص الكلي",
152
+ "فلترة متقدمة للمخرجات",
153
+ "معالجة النصوص العربية والإنجليزية"
154
+ ],
155
+ "example_requests": {
156
+ "extract_all": {
157
+ "url": "https://example.com"
158
+ },
159
+ "extract_ranges": {
160
+ "url": "https://example.com",
161
+ "ranges": [[0, 10], [50, 100]]
162
+ },
163
+ "get_count": {
164
+ "url": "https://example.com",
165
+ "timeout": 15
166
+ }
167
+ }
168
  }
169
 
170
  @app.get("/health")
171
  async def health_check():
172
+ return {
173
+ "status": "healthy",
174
+ "version": "2.0.0",
175
+ "modules": [
176
+ "text_extractor",
177
+ "output_clipper",
178
+ "fastapi"
179
+ ]
180
+ }
181
 
182
  if __name__ == "__main__":
183
  import uvicorn