Hydra-Bolt commited on
Commit
eef2a73
·
1 Parent(s): 0e65d5f

restructured

Browse files
Dockerfile CHANGED
@@ -25,4 +25,5 @@ RUN playwright install chromium
25
  # Copy app code
26
  COPY --chown=user . /app
27
 
28
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
25
  # Copy app code
26
  COPY --chown=user . /app
27
 
28
+ CMD ["uvicorn", "app/main:app", "--host", "0.0.0.0", "--port", "7860"]
29
+
{tools → app}/__init__.py RENAMED
File without changes
services.py → app/agent/services.py RENAMED
@@ -7,10 +7,10 @@ from langchain.output_parsers import PydanticOutputParser
7
  from langchain_core.prompts import PromptTemplate
8
  from dotenv import load_dotenv
9
 
10
- from models import NarratorExtractionResponse, NarratorAnalysisResponse
11
- from tools.scrape_shamela import ShamelaNarratorExtractor
12
 
13
- from constants import EXTRACT_PROMPT, ANALYZE_PROMPT, SYNTHESIS_PROMPT
14
  import asyncio
15
 
16
 
@@ -223,13 +223,6 @@ class LLMService:
223
  "success": True,
224
  }
225
 
226
- return {
227
- "overall_assessment": synthesis_result.content,
228
- "individual_results": chain_results,
229
- "chain_length": len(chain_results),
230
- "success": True,
231
- }
232
-
233
  except Exception as e:
234
  return {
235
  "overall_assessment": f"Synthesis failed: {str(e)}",
 
7
  from langchain_core.prompts import PromptTemplate
8
  from dotenv import load_dotenv
9
 
10
+ from app.db.models import NarratorExtractionResponse, NarratorAnalysisResponse
11
+ from app.tools.scrape_shamela import ShamelaNarratorExtractor
12
 
13
+ from app.config.constants import EXTRACT_PROMPT, ANALYZE_PROMPT, SYNTHESIS_PROMPT
14
  import asyncio
15
 
16
 
 
223
  "success": True,
224
  }
225
 
 
 
 
 
 
 
 
226
  except Exception as e:
227
  return {
228
  "overall_assessment": f"Synthesis failed: {str(e)}",
routes.py → app/api/routes.py RENAMED
@@ -2,7 +2,7 @@ from fastapi import APIRouter, HTTPException, status
2
  from fastapi.responses import JSONResponse
3
  from typing import List, Dict, Any
4
 
5
- from models import (
6
  HadithTextRequest,
7
  NarratorExtractionResponse,
8
  NarratorAnalysisRequest,
@@ -15,7 +15,7 @@ from models import (
15
  ChainAnalysisResult,
16
  ExtractAndAnalyzeMetadata,
17
  )
18
- from services import get_llm_service
19
 
20
  router = APIRouter(prefix="/api/v1", tags=["hadith-analysis"])
21
 
 
2
  from fastapi.responses import JSONResponse
3
  from typing import List, Dict, Any
4
 
5
+ from app.db.models import (
6
  HadithTextRequest,
7
  NarratorExtractionResponse,
8
  NarratorAnalysisRequest,
 
15
  ChainAnalysisResult,
16
  ExtractAndAnalyzeMetadata,
17
  )
18
+ from app.agent.services import get_llm_service
19
 
20
  router = APIRouter(prefix="/api/v1", tags=["hadith-analysis"])
21
 
app/config/__init__.py ADDED
File without changes
constants.py → app/config/constants.py RENAMED
File without changes
config.py → app/config/settings.py RENAMED
File without changes
app/db/__init__.py ADDED
File without changes
models.py → app/db/models.py RENAMED
File without changes
app.py → app/main.py RENAMED
@@ -4,8 +4,8 @@ from fastapi.responses import JSONResponse
4
  import uvicorn
5
  import os
6
 
7
- from config import settings
8
- from routes import router
9
 
10
 
11
  # Create FastAPI application
 
4
  import uvicorn
5
  import os
6
 
7
+ from app.config.settings import settings
8
+ from app.api.routes import router
9
 
10
 
11
  # Create FastAPI application
app/tools/__init__.py ADDED
File without changes
{tools → app/tools}/fetch.py RENAMED
@@ -289,45 +289,4 @@ async def fetch_html_with_browser(url, browser_type='chromium', max_retries=5, m
289
  await asyncio.sleep(wait_time)
290
 
291
  print(f"[FAIL] Could not fetch {url} with {browser_type} after {max_retries} attempts.")
292
- return None
293
-
294
- # Example usage
295
- async def main():
296
- """Example usage with async functions."""
297
- url = "https://shamela.ws/narrator/5710"
298
-
299
- print("=" * 60)
300
- print("Testing basic fetch_html function...")
301
- print("=" * 60)
302
-
303
- # Test basic function
304
- html = await fetch_html(url, headless=True) # Set headless=False to see the browser
305
- if html:
306
- with open("debug_shamela_basic.html", "w", encoding="utf-8") as f:
307
- f.write(html)
308
- print(f"[SUCCESS] Basic HTML saved to debug_shamela_basic.html ({len(html)} chars)")
309
- else:
310
- print("[FAILED] Could not fetch HTML with basic function")
311
-
312
- print("\n" + "=" * 60)
313
- print("Testing enhanced fetch_html_with_js_execution function...")
314
- print("=" * 60)
315
-
316
- # Test enhanced function
317
- html_js = await fetch_html_with_js_execution(url, headless=True, wait_for_js=True)
318
- if html_js:
319
- with open("debug_shamela_js.html", "w", encoding="utf-8") as f:
320
- f.write(html_js)
321
- print(f"[SUCCESS] Enhanced HTML saved to debug_shamela_js.html ({len(html_js)} chars)")
322
- else:
323
- print("[FAILED] Could not fetch HTML with enhanced function")
324
-
325
- # Compare results
326
- if html and html_js:
327
- print(f"\n[INFO] Basic HTML length: {len(html)} chars")
328
- print(f"[INFO] Enhanced HTML length: {len(html_js)} chars")
329
- print(f"[INFO] Difference: {abs(len(html_js) - len(html))} chars")
330
-
331
-
332
- if __name__ == "__main__":
333
- asyncio.run(main())
 
289
  await asyncio.sleep(wait_time)
290
 
291
  print(f"[FAIL] Could not fetch {url} with {browser_type} after {max_retries} attempts.")
292
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
{tools → app/tools}/scrape_shamela.py RENAMED
@@ -314,19 +314,3 @@ class ShamelaNarratorExtractor:
314
  print(f"Total scholars: {info['extraction_metadata']['total_scholars']}")
315
  print(f"Biographical fields: {info['extraction_metadata']['biographical_fields']}")
316
  print(f"Total comments: {info['extraction_metadata']['total_comments']}")
317
-
318
-
319
- # Example usage
320
- # Example usage
321
- async def main():
322
- """Example usage with async functions."""
323
- narrator_name = "أَبُو بَكْرِ بْنُ أَبِي شَيْبَةَ"
324
-
325
- # Extract narrator information using the class
326
- info = await ShamelaNarratorExtractor.extract_narrator_by_name(narrator_name)
327
-
328
- # Print the results
329
- ShamelaNarratorExtractor.print_narrator_info(info)
330
-
331
- if __name__ == "__main__":
332
- asyncio.run(main())
 
314
  print(f"Total scholars: {info['extraction_metadata']['total_scholars']}")
315
  print(f"Biographical fields: {info['extraction_metadata']['biographical_fields']}")
316
  print(f"Total comments: {info['extraction_metadata']['total_comments']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
asd.ipynb CHANGED
@@ -2,298 +2,64 @@
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
- "execution_count": 4,
6
- "id": "b4667bde",
7
- "metadata": {},
8
- "outputs": [
9
- {
10
- "name": "stdout",
11
- "output_type": "stream",
12
- "text": [
13
- "Searching for: \" ابن كثير\" site:shamela.ws/narrator\n",
14
- "Extracted works for narrator: ابن كثير\n",
15
- "NarratorInfo(narrator_name=None, biographical_info={}, scholarly_critique=[], extraction_metadata={'total_scholars': 0, 'biographical_fields': 0, 'has_critique_section': False, 'total_comments': 0})\n"
16
- ]
17
- }
18
- ],
19
- "source": [
20
- "from tools.scrape_shamela import ShamelaNarratorExtractor\n",
21
- "\n",
22
- "narrator_name = \" ابن كثير\"\n",
23
- "if __name__ == \"__main__\":\n",
24
- " extractor = ShamelaNarratorExtractor()\n",
25
- " details = extractor.search_and_extract(narrator_name)\n",
26
- " print(f\"Extracted works for narrator: {narrator_name}\")\n",
27
- " print(details)\n"
28
- ]
29
- },
30
- {
31
- "cell_type": "code",
32
- "execution_count": null,
33
- "id": "e2e25f79",
34
  "metadata": {},
35
  "outputs": [],
36
  "source": [
37
- "import requests\n",
38
  "from bs4 import BeautifulSoup\n",
39
- "from typing import Dict, List, Any\n",
40
- "from googlesearch import search\n",
41
- "\n",
42
- "def extract_narrator_info(html_content: str) -> Dict[str, Any]:\n",
43
- " \"\"\"\n",
44
- " Extract narrator information from Shamela.ws HTML content with better section separation.\n",
45
- " \n",
46
- " Args:\n",
47
- " html_content: HTML content from shamela.ws narrator page\n",
48
- " \n",
49
- " Returns:\n",
50
- " Dictionary containing extracted narrator information\n",
51
- " \"\"\"\n",
52
- " soup = BeautifulSoup(html_content, \"html.parser\")\n",
53
- " result = {}\n",
54
- "\n",
55
- " # 1. Extract Narrator Name (from <h1>)\n",
56
- " name_tag = soup.find(\"h1\")\n",
57
- " result[\"narrator_name\"] = name_tag.text.strip() if name_tag else None\n",
58
- "\n",
59
- " # 2. Extract Biographical Information (before الجرح والتعديل section)\n",
60
- " bio_info = {}\n",
61
- " container = soup.find(\"div\", class_=\"col-md-12\")\n",
62
- " \n",
63
- " # Keywords that indicate scholarly critique content (not biographical)\n",
64
- " critique_keywords = [\n",
65
- " \"ذكره\", \"قال\", \"وقال\", \"ثقة\", \"ضعيف\", \"صدوق\", \"كذاب\", \"متروك\",\n",
66
- " \"الثقات\", \"الضعفاء\", \"تهذيب\", \"الكاشف\", \"الميزان\", \"العجلي\",\n",
67
- " \"النسائي\", \"ابن سعد\", \"أحمد\", \"يعقوب\", \"ابن حبان\"\n",
68
- " ]\n",
69
- " \n",
70
- " if container:\n",
71
- " # Find the الجرح والتعديل header first\n",
72
- " critique_header = None\n",
73
- " for h4 in container.find_all(\"h4\"):\n",
74
- " if \"الجرح والتعديل\" in h4.text:\n",
75
- " critique_header = h4\n",
76
- " break\n",
77
- " \n",
78
- " # Process divs before the critique section\n",
79
- " for div in container.find_all(\"div\", recursive=False):\n",
80
- " # Stop when we reach the critique header\n",
81
- " if critique_header and div == critique_header:\n",
82
- " break\n",
83
- " \n",
84
- " b_tag = div.find(\"b\")\n",
85
- " if b_tag:\n",
86
- " key = b_tag.text.strip().rstrip(\":\").rstrip(\":\")\n",
87
- " \n",
88
- " # Skip if this looks like scholarly critique content\n",
89
- " is_critique_content = any(keyword in key for keyword in critique_keywords)\n",
90
- " if is_critique_content:\n",
91
- " continue\n",
92
- " \n",
93
- " # Get the text after the <b> tag\n",
94
- " remaining_text = \"\"\n",
95
- " for sibling in b_tag.next_siblings:\n",
96
- " if hasattr(sibling, 'strip'):\n",
97
- " remaining_text += sibling.strip()\n",
98
- " else:\n",
99
- " remaining_text += str(sibling).strip()\n",
100
- " \n",
101
- " # Additional check: if the content contains critique keywords, skip it\n",
102
- " if remaining_text:\n",
103
- " content_has_critique = any(keyword in remaining_text for keyword in critique_keywords)\n",
104
- " if not content_has_critique:\n",
105
- " bio_info[key] = remaining_text.strip()\n",
106
- "\n",
107
- " result[\"biographical_info\"] = bio_info\n",
108
- "\n",
109
- " # 3. Extract Scholarly Critique (after الجرح والتعديل header)\n",
110
- " scholarly_critique = []\n",
111
- " \n",
112
- " if container:\n",
113
- " critique_header = None\n",
114
- " for h4 in container.find_all(\"h4\"):\n",
115
- " if \"الجرح والتعديل\" in h4.text:\n",
116
- " critique_header = h4\n",
117
- " break\n",
118
- " \n",
119
- " if critique_header:\n",
120
- " current_scholar = None\n",
121
- " current_comments = []\n",
122
- " \n",
123
- " # Process all siblings after the critique header\n",
124
- " for element in critique_header.find_next_siblings():\n",
125
- " # Scholar name (in alert-info div)\n",
126
- " if (element.name == \"div\" and \n",
127
- " \"alert-info\" in element.get(\"class\", [])):\n",
128
- " \n",
129
- " # Save previous scholar's data if exists\n",
130
- " if current_scholar and current_comments:\n",
131
- " scholarly_critique.append({\n",
132
- " \"scholar\": current_scholar,\n",
133
- " \"comments\": current_comments.copy()\n",
134
- " })\n",
135
- " \n",
136
- " # Start new scholar\n",
137
- " current_scholar = element.text.strip()\n",
138
- " current_comments = []\n",
139
- " \n",
140
- " # Scholar comment (regular div)\n",
141
- " elif (element.name == \"div\" and \n",
142
- " not \"alert-info\" in element.get(\"class\", []) and\n",
143
- " element.text.strip()):\n",
144
- " \n",
145
- " comment_text = element.text.strip()\n",
146
- " \n",
147
- " # If no current scholar, extract scholar name from the comment\n",
148
- " if not current_scholar:\n",
149
- " # Look for patterns like \"قال ابن حبان\" or \"وذكره العجلي\"\n",
150
- " for word in comment_text.split():\n",
151
- " if any(scholar_name in word for scholar_name in \n",
152
- " [\"ابن حبان\", \"العجلي\", \"النسائي\", \"ابن سعد\", \"الذهبي\", \"ابن حجر\"]):\n",
153
- " current_scholar = \"مختلف العلماء\" # Mixed scholars\n",
154
- " break\n",
155
- " \n",
156
- " if not current_scholar:\n",
157
- " current_scholar = \"غير محدد\" # Unspecified\n",
158
- " \n",
159
- " # Extract bold text if present\n",
160
- " bold_tags = element.find_all(\"b\")\n",
161
- " comment = {\n",
162
- " \"text\": comment_text,\n",
163
- " \"highlighted\": [b.text.strip() for b in bold_tags] if bold_tags else []\n",
164
- " }\n",
165
- " current_comments.append(comment)\n",
166
- " \n",
167
- " # Don't forget the last scholar\n",
168
- " if current_scholar and current_comments:\n",
169
- " scholarly_critique.append({\n",
170
- " \"scholar\": current_scholar,\n",
171
- " \"comments\": current_comments\n",
172
- " })\n",
173
- "\n",
174
- " result[\"scholarly_critique\"] = scholarly_critique\n",
175
- "\n",
176
- " # 4. Extract metadata\n",
177
- " result[\"extraction_metadata\"] = {\n",
178
- " \"total_scholars\": len(scholarly_critique),\n",
179
- " \"biographical_fields\": len(bio_info),\n",
180
- " \"has_critique_section\": len(scholarly_critique) > 0,\n",
181
- " \"total_comments\": sum(len(scholar[\"comments\"]) for scholar in scholarly_critique)\n",
182
- " }\n",
183
- "\n",
184
- " return result\n",
185
- "\n",
186
- "def clean_biographical_info(bio_info: Dict[str, str]) -> Dict[str, str]:\n",
187
- " \"\"\"\n",
188
- " Additional cleaning function to remove any remaining critique content from bio info.\n",
189
- " \"\"\"\n",
190
- " cleaned_bio = {}\n",
191
- " \n",
192
- " # Define purely biographical field patterns\n",
193
- " bio_field_patterns = [\n",
194
- " \"الاسم\", \"الكنية\", \"النسب\", \"بلد\", \"تاريخ\", \"طبقة\", \"علاقات\"\n",
195
- " ]\n",
196
- " \n",
197
- " for key, value in bio_info.items():\n",
198
- " # Keep if it's clearly a biographical field\n",
199
- " if any(pattern in key for pattern in bio_field_patterns):\n",
200
- " cleaned_bio[key] = value\n",
201
- " # Or if it doesn't contain critique-style language\n",
202
- " elif not any(word in value for word in [\"قال\", \"ذكره\", \"ثقة\", \"ضعيف\"]):\n",
203
- " cleaned_bio[key] = value\n",
204
- " \n",
205
- " return cleaned_bio\n",
206
- "\n",
207
- "# Updated main extraction function\n",
208
- "def extract_narrator_info_enhanced(html_content: str) -> Dict[str, Any]:\n",
209
- " \"\"\"Enhanced extraction with better cleaning.\"\"\"\n",
210
- " result = extract_narrator_info(html_content)\n",
211
- " \n",
212
- " # Apply additional cleaning to biographical info\n",
213
- " result[\"biographical_info\"] = clean_biographical_info(result[\"biographical_info\"])\n",
214
- " \n",
215
- " return result"
216
  ]
217
  },
218
  {
219
  "cell_type": "code",
220
- "execution_count": 6,
221
- "id": "50c33021",
222
  "metadata": {},
223
  "outputs": [
224
  {
225
  "name": "stdout",
226
  "output_type": "stream",
227
  "text": [
228
- "Searching for narrator: مُحَمَّدُ بْنُ عَبْدِ الرَّحْمَنِ الْعَنْبَرِيُّ\n",
229
- "Google search query: مُحَمَّدُ بْنُ عَبْدِ الرَّحْمَنِ الْعَنْبَرِيُّ site:shamela.ws/narrator\n",
230
- "Search results: ['https://shamela.ws/narrator/5710', 'https://shamela.ws/narrator/3414', 'https://shamela.ws/narrator/484', 'https://shamela.ws/narrator/3133', 'https://shamela.ws/narrator/3340']\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  ]
232
  }
233
  ],
234
  "source": [
235
- "narrator_name = \"مُحَمَّدُ بْنُ عَبْدِ الرَّحْمَنِ الْعَنْبَرِيُّ\"\n",
236
- "\n",
237
- "if __name__ == \"__main__\":\n",
238
- " # Use googlesearch to find the narrator page on shamela.ws\n",
239
- " query = f'{narrator_name.strip()} site:shamela.ws/narrator'\n",
240
- " search_results = list(search(query, num_results=5))\n",
241
- "\n",
242
- " print(f\"Searching for narrator: {narrator_name}\")\n",
243
- " print(f\"Google search query: {query}\")\n",
244
- " print(f\"Search results: {search_results}\")\n",
245
- "\n",
246
- " # if search_results:\n",
247
- " # # Extract URL from SearchResult object\n",
248
- " # url = search_results[0] if hasattr(search_results[0], 'url') else str(search_results[0])\n",
249
- " # print(f\"Found narrator page: {url}\")\n",
250
- " \n",
251
- " # # Fetch the HTML content\n",
252
- " # response = requests.get(url)\n",
253
- " # if response.status_code == 200:\n",
254
- " # html_content = response.text\n",
255
- " # info = extract_narrator_info_enhanced(html_content)\n",
256
- " # else:\n",
257
- " # print(f\"Failed to fetch page: {response.status_code}\")\n",
258
- " # info = {}\n",
259
- "\n",
260
- " # else:\n",
261
- " # info = {\n",
262
- " # \"narrator_name\": narrator_name,\n",
263
- " # \"biographical_info\": {},\n",
264
- " # \"scholarly_critique\": [],\n",
265
- " # \"extraction_metadata\": {\n",
266
- " # \"total_scholars\": 0,\n",
267
- " # \"biographical_fields\": 0,\n",
268
- " # \"has_critique_section\": True,\n",
269
- " # \"total_comments\": 0\n",
270
- " # }\n",
271
- " # }\n",
272
- "\n",
273
- " # print(\"=== NARRATOR INFORMATION ===\")\n",
274
- " # print(f\"Name: {info['narrator_name']}\")\n",
275
- " # print(f\"\\n=== BIOGRAPHICAL INFO ===\")\n",
276
- " # for key, value in info['biographical_info'].items():\n",
277
- " # print(f\"{key}: {value}\")\n",
278
- "\n",
279
- " # print(f\"\\n=== SCHOLARLY CRITIQUE ===\")\n",
280
- " # for scholar_data in info['scholarly_critique']:\n",
281
- " # print(f\"\\nScholar: {scholar_data['scholar']}\")\n",
282
- " # for comment in scholar_data['comments']:\n",
283
- " # print(f\" - {comment['text']}\")\n",
284
- " # if comment['highlighted']:\n",
285
- " # print(f\" Highlighted: {comment['highlighted']}\")\n",
286
- "\n",
287
- " # print(f\"\\n=== METADATA ===\")\n",
288
- " # print(f\"Total scholars: {info['extraction_metadata']['total_scholars']}\")\n",
289
- " # print(f\"Biographical fields: {info['extraction_metadata']['biographical_fields']}\")\n",
290
- " # print(f\"Total comments: {info['extraction_metadata']['total_comments']}\")\n"
291
  ]
292
  },
293
  {
294
  "cell_type": "code",
295
  "execution_count": null,
296
- "id": "6ff2b660",
297
  "metadata": {},
298
  "outputs": [],
299
  "source": []
 
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
+ "execution_count": 6,
6
+ "id": "f41e65f6",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  "metadata": {},
8
  "outputs": [],
9
  "source": [
 
10
  "from bs4 import BeautifulSoup\n",
11
+ "from tools.fetch import fetch_html\n",
12
+ "\n",
13
+ "async def scrape_siyar_alaam_nubala():\n",
14
+ " html = await fetch_html(\"https://www.islamweb.net/ar/library/content/60/531/%D8%B3%D8%B9%D9%8A%D8%AF-%D8%A8%D9%86-%D8%A7%D9%84%D9%85%D8%B3%D9%8A%D8%A8\")\n",
15
+ " if html is None:\n",
16
+ " return []\n",
17
+ " soup = BeautifulSoup(html, \"html.parser\")\n",
18
+ " divs = soup.find_all(\"div\", class_=\"bookcontent-dic\")\n",
19
+ " texts = [div.get_text(strip=True) for div in divs]\n",
20
+ " return texts\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  ]
22
  },
23
  {
24
  "cell_type": "code",
25
+ "execution_count": 7,
26
+ "id": "c50a7413",
27
  "metadata": {},
28
  "outputs": [
29
  {
30
  "name": "stdout",
31
  "output_type": "stream",
32
  "text": [
33
+ "[INFO] Fetching https://www.islamweb.net/ar/library/content/60/531/%D8%B3%D8%B9%D9%8A%D8%AF-%D8%A8%D9%86-%D8%A7%D9%84%D9%85%D8%B3%D9%8A%D8%A8 (Attempt 1/5)\n"
34
+ ]
35
+ },
36
+ {
37
+ "name": "stdout",
38
+ "output_type": "stream",
39
+ "text": [
40
+ "[OK] https://www.islamweb.net/ar/library/content/60/531/%D8%B3%D8%B9%D9%8A%D8%AF-%D8%A8%D9%86-%D8%A7%D9%84%D9%85%D8%B3%D9%8A%D8%A8 (Attempt 1) | Preview: <!DOCTYPE html><html><head> \t\t<meta charset=\"utf-8\"> \t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"> \t\t<meta name=\"language\" content=\"ar\"> \t\t ...\n",
41
+ "['سعيد بن المسيب ( ع )ابن حزن بن أبي وهب بن عمرو بن عائذ بن عمران بن مخزوم بن يقظة ، الإمام العلم ، أبو محمد القرشي المخزومي ، عالمأهلالمدينة، وسيد التابعين في زمانه . ولد[ص:218 ]لسنتين مضتا من خلافةعمررضي الله عنه وقيل : لأربع مضين منهابالمدينة.رأىعمر، وسمععثمان،وعليا،nindex.php?page=showalam&ids=47وزيد بن ثابت،وأبا موسى،وسعدا،nindex.php?page=showalam&ids=25وعائشةnindex.php?page=showalam&ids=3وأبا هريرة،nindex.php?page=showalam&ids=11وابن عباس،ومحمد بن مسلمة،nindex.php?page=showalam&ids=54وأم سلمة، وخلقا سواهم . وقيل : إنه سمع منعمر.وروى عنأبي بن كعبمرسلا ،وبلالكذلك ،nindex.php?page=showalam&ids=228وسعد بن عبادةكذلك ،وأبي ذرnindex.php?page=showalam&ids=4وأبي الدرداءكذلك ، وروايته عنعلي،وسعد،وعثمان،وأبي موسى،nindex.php?page=showalam&ids=25وعائشة،nindex.php?page=showalam&ids=11598وأم شريك،nindex.php?page=showalam&ids=12وابن عمر،nindex.php?page=showalam&ids=3وأبي هريرة،nindex.php?page=showalam&ids=11وابن عباس،nindex.php?page=showalam&ids=137وحكيم بن حزام،nindex.php?page=showalam&ids=12وعبد الله بن عمرو، وأبيهالمسيب،وأبي سعيدفي \" الصحيحين \" وعنحسان بن ثابت،nindex.php?page=showalam&ids=90وصفوان بن أمية،ومعمر بن عبد الله،ومعاوية،nindex.php?page=showalam&ids=54وأم سلمة، في صحيحمسلم. وروايته عنجبير بن مطعموجابر، وغيرهما فيnindex.php?page=showalam&ids=12070البخاري. وروايته عنعمرفي السنن الأربعة .وروى -أيضا- عنnindex.php?page=showalam&ids=47زيد بن ثابت،وسراقة بن مالك،وصهيب،والضحاك بن سفيان،وعبد الرحمن بن عثمان التيمي، وروايته عنعتاب بن أسيدفي السنن الأربعة ، وهو مرسل . وأرسل عن النبي -صلى الله عليه وسلم- وعنnindex.php?page=showalam&ids=1أبي بكر الصديقوكان زوج بنتnindex.php?page=showalam&ids=3أبي هريرة، وأعلم الناس بحديثه .روى عنه خلق : منهمإدريس بن صبيح،وأسامة بن زيد الليثي،وإسماعيل بن أمية، وبشيروعبد الرحمن بن حرملةوعبد الرحمن بن حميد بن عبد الرحمن،nindex.php?page=showalam&ids=16395وعبد الكريم الجزري،nindex.php?page=showalam&ids=16480وعبد ��لمجيد بن سهيل،وعبيد الله بن سليمان العبدي،وعثمان بن حكيم،nindex.php?page=showalam&ids=16566وعطاء الخراساني،وعقبة بن حريث[ص:219 ]وعلي بن جدعان،وعلي بن نفيل الحراني،وعمارة بن عبد الله بن طعمة،nindex.php?page=showalam&ids=16709وعمرو بن شعيب،nindex.php?page=showalam&ids=16705وعمرو بن دينار،nindex.php?page=showalam&ids=16718وعمرو بن مرة،وعمرو بن مسلم الليثي،وغيلان بن جرير،والقاسم بن عاصم، وابنهمحمد بن سعيد،وقتادة،ومحمد بن صفوان،ومحمد بن عبد الرحمن بن أبي لبيبة،nindex.php?page=showalam&ids=11958وأبو جعفر محمد بن علي،ومحمد بن عمرو بن عطاء،nindex.php?page=showalam&ids=12300والزهري،nindex.php?page=showalam&ids=16920وابن المنكدر،ومعبد بن هرمز،ومعمر بن أبي حبيبة،nindex.php?page=showalam&ids=17183وموسى بن وردان،وميسرة الأشجعي،nindex.php?page=showalam&ids=17188وميمون بن مهران،وأبو سهيل نافع بن مالك،وأبو معشر نجيح السندي، وهو عندالترمذي،وهاشم بن هاشم الوقاصي،ويحيى بن سعيد الأنصاري،ويزيد بن قسيط،ويزيد بن نعيم بن هزال،nindex.php?page=showalam&ids=17384ويعقوب بن عبد الله بن الأشج،ويونس بن سيف،وأبو جعفر الخطميوأبو قرة الأسدي، من \" التهذيب \" .وعنه :الزهري،وقتادة،nindex.php?page=showalam&ids=16705وعمرو بن دينار،ويحيى بن سعيد الأنصاري،nindex.php?page=showalam&ids=15562وبكير بن الأشج،nindex.php?page=showalam&ids=15854وداود بن أبي هند،nindex.php?page=showalam&ids=228وسعد بن إبراهيم،nindex.php?page=showalam&ids=16621وعلي بن زيد بن جدعان،nindex.php?page=showalam&ids=16100وشريك بن أبي نمر،وعبد الرحمن بن حرملةوبشر كثير .وكان ممن برز في العلم والعمل ، وقع لنا جملة من عالي حديثه .أخبرناأبو المعالي أحمد بن إسحاق القرافي، أنبأناالفتح بن عبد الله الكاتب، أنبأنامحمد بن عمر الشافعي،ومحمد بن أحمد الطرائفي،ومحمد بن علي بن الداية، قالوا : أنبأناأبو جعفر محمد بن أحمد بن المسلمة، أنبأناعبيد الله بن عبد الرحمن الزهريسنة ثمانين وثلاث مائة ، أنبأناجعفر بن[ص:220 ]محمد الفريابي، حدثناإبراهيم بن الحجاج السامي، حدثناحماد بن سلمة، عنnindex.php?page=showalam&ids=15854داود بن أبي هند، عنnindex.php?page=showalam&ids=15990سعيد بن المسيب، عنnindex.php?page=showalam&ids=3أبي هريرة-رضي الله عنه- ، أن رسول الله -صلى الله عليه وسلم- قال :nindex.php?page=hadith&LINKID=880037ثلاث من كن فيه فهو منافق وإن صام وصلى ، وزعم أنه مسلم : من إذا حدث كذب ، وإذا وعد أخلف ، وإذا ائتمن خان.هذا صحيح ، عال ، فيه دليل على أن هذه الخصال من كبار الذنوب .أخرجهمسلمعنnindex.php?page=showalam&ids=12175أبي نصر التمار، عنحماد بن سلمة، فوقع لنا بدلا عاليا مع علوه في نفسهلمسلمولنا ; فإن أعلى أنواع الإبدال أن يكون الحديث من أعلى حديث صاحب ذلك الكتاب ، ويقع لك بإسناد آخر أعلى بدرجة أو أكثر . والله أعلم .أخبرناإسحاق الأسدي، أنبأنايوسف الآدمي( ح ) وأنبأناأحمد بن سلامةقالا : أنبأناأبو المكارم الأصبهاني، قاليوسف سماعا، وقال الآخر إجازة : أنبأناأبو علي الحداد، أنبأناأبو نعيم، حدثناسليمان بن أحمد، حدثناأحمد بن داود المكي، حدثناحبيب كاتب مالك، حدثنا ابن أخيالزهري، عنالزهري، عنnindex.php?page=showalam&ids=15990سعيد بن المسيب، عنأبي بن كعب، قال : قال رسول الله -صلى الله عليه وسلم- :قال ليجبريل: ليبك الإسلام على موتعمر.هذا حديث منكر ،وحبيبليس بثقة ، مع أنسعيداعنأبيمنقطع .عبد العزيز بن المختار، عنعلي بن زيد، حدثنيسعيد بن المسيب بن حزنnindex.php?page=hadith&LINKID=880039أن جدهحزناأتى النبي -صلى الله عليه وسلم- فقال : ما اسمك؟ قال :حزن. قال : بل أنتسهل. قال : يا رسول الله ، اسم سماني به أبواي وعرفت به في الناس ، فسكت عنه النبي صلى الله عليه وسلم قالسعيد: فما زلنا تعرف الحزونة فينا أهل البيت.[ص:221 ]هذا حديث مرسل ، ومراسيلسعيدمحتج بها ، لكنعلي بن زيدليس بالحجة ، وأما الحديث فمروي بإسناد صحيح ، متصل ، ولفظه :nindex.php?page=hadith&LINKID=880040أن النبي -صلى الله عليه وسلم- قال له : ما اسمك؟ قال :حزن. قال : أنتسهل. فقال لا أغير اسما سمانيه أبي قالسعيد: فما زالت تلك الحزونة فينا بعد.العطاف بن خالد: عنأبي حرملة، عنابن المسيبقال : ما فاتتني الصلاة في جماعة منذ أربعين سنة .nindex.php?page=showalam&ids=16004سفيان الثوري: عنعثمان بن حكيم، سمعتnindex.php?page=showalam&ids=15990سعيد بن المسيبيقول : ما أذن المؤذن منذ ثلاثين سنة إلا وأنا في المسجد . إسناده ثابت .حماد بن زيد: حدثنايزيد بن حازم، أنnindex.php?page=showalam&ids=15990سعيد بن المسيبكان يسرد الصوم .مسعرعنسعيد بن إبراهيم، سمعابن المسيبيقول : ما أحد أعلم بقضاء قضاه رسول الله -صلى الله عليه وسلم- ولاأبو بكر، ولاعمرمني .[ص:222 ]أسامة بن زيد: عننافع، أنابن عمرذكرnindex.php?page=showalam&ids=15990سعيد بن المسيبفقال : هو -والله- أحد المفتين .قالnindex.php?page=showalam&ids=12251أحمد بن حنبلوغير واحد : مرسلاتnindex.php?page=showalam&ids=15990سعيد بن المسيبصحاح .وقالقتادة،ومكحول،nindex.php?page=showalam&ids=12300والزهري، وآخرون ، واللفظلقتادة: ما رأيت أعلم منnindex.php?page=showalam&ids=15990سعيد بن المسيب.قالnindex.php?page=showalam&ids=16604علي بن المديني: لا أعلم في التابعين أحدا أوسع علما منابن المسيب، هو عندي أجل التابعين .عبد الرحمن بن حرملة: سمعتابن المسيبيقول : حججت أربعين حجة .قاليحيى بن سعيد الأنصاري: كانسعيديكثر أن يقول في مجلسه : اللهم سلم سلم .معن : سمعتnindex.php?page=showalam&ids=16867مالكايقول : قالابن المسيب: إن كنت لأسير الأيام والليالي في طلب الحديث الواحد .ابن عيينة: عنإبراهيم بن طريف، عنحميد بن يعقوب، سمعnindex.php?page=showalam&ids=15990سعيد بن المسيبيقول : سمعت منعمركلمة ما بقي أحد سمعها غيري .أبو إسحاق الشيباني: عنبكير بن الأخنس، عنسعيد بن[ص:223 ]المسيب، قال : سمعتعمرعلى المنبر وهو يقول : لا أجد أحدا جامع فلم يغتسل ، أنزل أو لم ينزل ، إلا عاقبته .ابن عيينة : عنيحيى بن سعيد، عنابن المسيب، قال : ولدت لسنتين مضتا من خلافةعمروكانت خلافته عشر سنين وأربعة أشهر .', 'سَعِيدُ بْنُ الْمُسَيَّبِ ( ع )ابْنُ حَزْنِ بْنِ أَبِي وَهْبِ بْنِ عَمْرِو بْنِ عَائِذِ بْنِ عِمْرَانَ بْنِ مَخْزُومِ بْنِ يَقَظَةَ ، الْإِمَامُ الْعَلَمُ ، أَبُو مُحَمَّدٍ الْقُرَشِيُّ الْمَخْزُومِيُّ ، عَالِمُأَهْلِالْمَدِينَةِ، وَسَيِّدُ التَّابِعِينَ فِي زَمَانِهِ . وُلِدَ[ص:218 ]لِسَنَتَيْنِ مَضَتَا مِنْ خِلَافَةِعُمَرَرَضِيَ اللَّهُ عَنْهُ وَقِيلَ : لِأَرْبَعٍ مَضَيْنَ مِنْهَابِالْمَدِينَةِ.رَأَىعُمَرَ، وَسَمِعَعُثْمَانَ،وَعَلِيًّا،nindex.php?page=showalam&ids=47وَزَيْدَ بْنَ ثَابِتٍ،وَأَبَا مُوسَى،وَسَعْدًا،nindex.php?page=showalam&ids=25وَعَائِشَةَnindex.php?page=showalam&ids=3وَأَبَا هُرَيْرَةَ،nindex.php?page=showalam&ids=11وَابْنَ عَبَّاسٍ،وَمُحَمَّدَ بْنَ مَسْلَمَةَ،nindex.php?page=showalam&ids=54وَأُمَّ سَلَمَةَ، وَخَلْقًا سِوَاهُمْ . وَقِيلَ : إِنَّهُ سَمِعَ مِنْعُمَرَ.وَرَوَى عَنْأُبَيِّ بْنِ كَعْبٍمُرْسَلًا ،وَبِلَالٍكَذَلِكَ ،nindex.php?page=showalam&ids=228وَسَعْدِ بْنِ عُبَادَةَكَذَلِكَ ،وَأَبِي ذَرٍّnindex.php?page=showalam&ids=4وَأَبِي الدَّرْدَاءِكَذَلِكَ ، وَرِوَايَتُهُ عَنْعَلِيٍّ،وَسَعْدٍ،وَعُثْمَانَ،وَأَبِي مُوسَى،nindex.php?page=showalam&ids=25وَعَائِشَةَ،nindex.php?page=showalam&ids=11598وَأُمِّ شَرِيكٍ،nindex.php?page=showalam&ids=12وَابْنِ عُمَرَ،nindex.php?page=showalam&ids=3وَأَبِي هُرَيْرَةَ،nindex.php?page=showalam&ids=11وَابْنِ عَبَّاسٍ،nindex.php?page=showalam&ids=137وَحَكِيمِ بْنِ حِزَامٍ،nindex.php?page=showalam&ids=12وَعَبْدِ اللَّهِ بْنِ عَمْرٍو، وَأَبِيهِالْمُسَيَّبِ،وَأَبِي سَعِيدٍفِي \" الصَّحِيحَيْنِ \" وَعَنْحَسَّانَ بْنِ ثَابِتٍ،nindex.php?page=showalam&ids=90وَصَفْوَانَ بْنِ أُمَيَّةَ،وَمَعْمَرِ بْنِ عَبْدِ اللَّهِ،وَمُعَاوِيَةَ،nindex.php?page=showalam&ids=54وَأُمِّ سَلَمَةَ، فِي صَحِيحِمُسْلِمٍ. وَرِوَايَتُهُ عَنْجُبَيْرِ بْنِ مُطْعِمٍوَجَابِرٍ، وَغَيْرِهِمَا فِيnindex.php?page=showalam&ids=12070الْبُخَارِيِّ. وَرِوَايَتُهُ عَنْعُمَرَفِي السُّنَنِ الْأَرْبَعَةِ .وَرَوَى -أَيْضًا- عَنْnindex.php?page=showalam&ids=47زَيْدِ بْنِ ثَابِتٍ،وَسُرَاقَةَ بْنِ مَالِكٍ،وَصُهَيْبٍ،وَالضَّحَّاكِ بْنِ سُفْيَانَ،وَعَبْدِ الرَّحْمَنِ بْنِ عُثْمَانَ التَّيْمِيِّ، وَرِوَايَتُهُ عَنْعَتَّابِ بْنِ أَسِيدٍفِي السُّنَنِ الْأَرْبَعَةِ ، وَهُوَ مُرْسَلٌ . وَأَرْسَلَ عَنِ النَّبِيِّ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- وَعَنْnindex.php?page=showalam&ids=1أَبِي بَكْرٍ الصِّدِّيقِوَكَانَ زَوْجَ بِنْتِnindex.php?page=showalam&ids=3أَبِي هُرَيْرَةَ، وَأَعْلَمَ النَّاسِ بِحَدِيثِهِ .رَوَى عَنْهُ خَلْقٌ : مِنْهُمْإِدْرِيسُ بْنُ صُبَيْحٍ،وَأُسَامَةُ بْنُ زَيْدٍ اللَّيْثِيُّ،وَإِسْمَاعِيلُ بْنُ أُمَيَّةَ، وَبَشِيرٌوَعَبْدُ الرَّحْمَنِ بْنُ حَرْمَلَةَوَعَبْدُ الرَّحْمَنِ بْنُ حُمَيْدِ بْنِ عَبْدِ الرَّحْمَنِ،nindex.php?page=showalam&ids=16395وَعَبْدُ الْكَرِيمِ الْجَزَرِيُّ،nindex.php?page=showalam&ids=16480وَعَبْدُ الْمَجِيدِ بْنُ سُهَيْلٍ،وَعُبَيْدُ اللَّهِ بْنُ سُلَيْمَانَ الْعَبْدِيُّ،وَعُثْمَانُ بْنُ حَكِيمٍ،nindex.php?page=showalam&ids=16566وَعَطَاءٌ الْخُرَاسَانِيُّ،وَعُقْبَةُ بْنُ حُرَيْثٍ[ص:219 ]وَعَلِيُّ بْنُ جُدْعَانَ،وَعَلِيُّ بْنُ نُفَيْلٍ الْحَرَّانِيُّ،وَعُمَارَةُ بْنُ عَبْدِ اللَّهِ بْنِ طُعْمَةَ،nindex.php?page=showalam&ids=16709وَعَمْرُو بْنُ شُعَيْبٍ،nindex.php?page=showalam&ids=16705وَعَمْرُو بْنُ دِينَارٍ،nindex.php?page=showalam&ids=16718وَعَمْرُو بْنُ مُرَّةَ،وَعَمْرُو بْنُ مُسْلِمٍ اللَّيْثِيُّ،وَغَيْلَانُ بْنُ جَرِيرٍ،وَالْقَاسِمُ بْنُ عَاصِمٍ، وَابْنُهُمُحَمَّدُ بْنُ سَعِيدٍ،وَقَتَادَةُ،وَمُحَمَّدُ بْنُ صَفْوَانَ،وَمُحَمَّدُ بْنُ عَبْدِ الرَّحْمَنِ بْنِ أَبِي لَبِيبَةَ،nindex.php?page=showalam&ids=11958وَأَبُو جَعْفَرٍ مُحَمَّدُ بْنُ عَلِيٍّ،وَمُحَمَّدُ بْنُ عَمْرِو بْنِ عَطَاءٍ،nindex.php?page=showalam&ids=12300وَالزُّهْرِيُّ،nindex.php?page=showalam&ids=16920وَابْنُ الْمُنْكَدِرِ،وَمَعْبَدُ بْنُ هُرْمُزٍ،وَمَعْمَرُ بْنُ أَبِي حَبِيبَةَ،nindex.php?page=showalam&ids=17183وَمُوسَى بْنُ وَرْدَانَ،وَمَيْسَرَةُ الْأَشْجَعِيُّ،nindex.php?page=showalam&ids=17188وَمَيْمُونُ بْنُ مِهْرَانَ،وَأَبُو سُهَيْلٍ نَافِعُ بْنُ مَالِكٍ،وَأَبُو مَعْشَرٍ نَجِيحُ السِّنْدِيُّ، وَهُوَ عِنْدَالتِّرْمِذِيِّ،وَهَاشِمُ بْنُ هَاشِمٍ الْوَقَّاصِي،وَيَحْيَى بْنُ سَعِيدٍ الْأَنْصَارِيُّ،وَيَزِيدُ بْنُ قُسَيْطٍ،وَيَزِيدُ بْنُ نُعَيْمِ بْنِ هُزَالٍ،nindex.php?page=showalam&ids=17384وَيَعْقُوبُ بْنُ عَبْدِ اللَّهِ بْنِ الْأَشَجِّ،وَيُونُسُ بْنُ سَيْفٍ،وَأَبُو جَعْفَرٍ الْخَطْمِيُّوَأَبُو قُرَّةَ الْأَسَدِيُّ، مِنَ \" التَّهْذِيبِ \" .وَعَنْهُ :الزُّهْرِيُّ،وَقَتَادَةُ،nindex.php?page=showalam&ids=16705وَعَمْرُو بْنُ دِينَارٍ،وَيَحْيَى بْنُ سَعِيدٍ الْأَنْصَارِيُّ،nindex.php?page=showalam&ids=15562وَبُكَيْرُ بْنُ الْأَشَجِّ،nindex.php?page=showalam&ids=15854وَدَاوُدُ بْنُ أَبِي هِنْدٍ،nindex.php?page=showalam&ids=228وَسَعْدُ بْنُ إِبْرَاهِيمَ،nindex.php?page=showalam&ids=16621وَعَلِيُّ بْنُ زَيْدِ بْنِ جُدْعَانَ،nindex.php?page=showalam&ids=16100وَشَرِيكُ بْنُ أَبِي نَمِرٍ،وَعَبْدُ الرَّحْمَنِ بْنُ حَرْمَلَةَوَبَشَرٌ كَثِيرٌ .وَكَانَ مِمَّنْ بَرَزَ فِي الْعِلْمِ وَالْعَمَلِ ، وَقَعَ لَنَا جُمْلَةٌ مِنْ عَالِي حَدِيثِهِ .أَخْبَرَنَاأَبُو الْمَعَالِي أَحْمَدُ بْنُ إِسْحَاقَ الْقَرَافِيُّ، أَنْبَأَنَاالْفَتْحُ بْنُ عَبْدِ اللَّهِ الْكَاتِبُ، أَنْبَأَنَامُحَمَّدُ بْنُ عُمَرَ الشَّافِعِيُّ،وَمُحَمَّدُ بْنُ أَحْمَدَ الطَّرَائِفِيُّ،وَمُحَمَّدُ بْنُ عَلِيِّ بْنِ الدَّايَةِ، قَالُوا : أَنْبَأَنَاأَبُو جَعْفَرٍ مُحَمَّدُ بْنُ أَحْمَدَ بْنِ الْمُسْلِمَةِ، أَنْبَأَنَاعُبَيْدُ اللَّهِ بْنُ عَبْدِ الرَّحْمَنِ الزُّهْرِيُّسَنَةَ ثَمَانِينَ وَثَلَاثِ مِائَةٍ ، أَنْبَأَنَاجَعْفَرُ بْنُ[ص:220 ]مُحَمَّدٍ الْفِرْيَابِيُّ، حَدَّثَنَاإِبْرَاهِيمُ بْنُ الْحَجَّاجِ السَّامِيُّ، حَدَّثَنَاحَمَّادُ بْنُ سَلَمَةَ، عَنْnindex.php?page=showalam&ids=15854دَاوُدَ بْنِ أَبِي هِنْدٍ، عَنْnindex.php?page=showalam&ids=15990سَعِيدِ بْنِ الْمُسَيَّبِ، عَنْnindex.php?page=showalam&ids=3أَبِي هُرَيْرَةَ-رَضِيَ اللَّهُ عَنْهُ- ، أَنَّ رَسُولَ اللَّهِ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- قَالَ :nindex.php?page=hadith&LINKID=880037ثَلَاثٌ مَنْ كُنَّ فِيهِ فَهُوَ مُنَافِقٌ وَإِنْ صَامَ وَصَلَّى ، وَزَعَمَ أَنَّهُ مُسْلِمٌ : مَنْ إِذَا حَدَّثَ كَذَبَ ، وَإِذَا وَعَدَ أَخْلَفَ ، وَإِذَا ائْتُمِنَ خَانَ.هَذَا صَحِيحٌ ، عَالٍ ، فِيهِ دَلِيلٌ عَلَى أَنَّ هَذِهِ الْخِصَالَ مِنْ كِبَارِ الذُّنُوبِ .أَخْرَجَهُمُسْلِمٌعَنْnindex.php?page=showalam&ids=12175أَبِي نَصْرٍ التَّمَّارِ، عَنْحَمَّادِ بْنِ سَلَمَةَ، فَوَقَعَ لَنَا بَدَلًا عَالِيًا مَعَ عُلُوِّهِ فِي نَفْسِهِلِمُسْلِمٍوَلَنَا ; فَإِنَّ أَعْلَى أَنْوَاعِ الْإِبْدَالِ أَنْ يَكُونَ الْحَدِيثُ مِنْ أَعْلَى حَدِيثِ صَاحِبِ ذَلِكَ الْكِتَابِ ، وَيَقَعُ لَكَ بِإِسْنَادٍ آخَرَ أَعْلَى بِدَرَجَةٍ أَوْ أَكْثَرَ . وَاللَّهُ أَعْلَمُ .أَخْبَرَنَاإِسْحَاقُ الْأَسَدِيُّ، أَنْبَأَنَايُوسُفُ الْآدَمِيُّ( ح ) وَأَنْبَأَنَاأَحْمَدُ بْنُ سَلَامَةَقَالَا : أَنْبَأَنَاأَبُو الْمَكَارِمِ الْأَصْبَهَانِيُّ، قَالَيُوسُفُ سَمَاعًا، وَقَالَ الْآخَرُ إِجَازَةً : أَنْبَأَنَاأَبُو عَلِيٍّ الْحَدَّادُ، أَنْبَأَنَاأَبُو نُعَيْمٍ، حَدَّثَنَاسُلَيْمَانُ بْنُ أَحْمَدَ، حَدَّثَنَاأَحْمَدُ بْنُ دَاوُدَ الْمَكِّيُّ، حَدَّثَنَاحَبِيبٌ كَاتِبُ مَالِكٍ، حَدَّثَنَا ابْنُ أَخِيالزُّهْرِيِّ، عَنِالزُّهْرِيِّ، عَنْnindex.php?page=showalam&ids=15990سَعِيدِ بْنِ الْمُسَيَّبِ، عَنْأُبَيِّ بْنِ كَعْبٍ، قَالَ : قَالَ رَسُولُ اللَّهِ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- :قَالَ لِيجِبْرِيلُ: لِيَبْكِ الْإِسْلَامُ عَلَى مَوْتِعُمَرَ.هَذَا حَدِيثٌ مُنْكَرٌ ،وَحَبِيبٌلَيْسَ بِثِقَةٍ ، مَعَ أَنَّسَعِيدًاعَنْأُبَيٍّمُنْقَطِعٌ .عَبْدُ الْعَزِيزِ بْنُ الْمُخْتَارِ، عَنْعَلِيِّ بْنِ زَيْدٍ، حَدَّثَنِيسَعِيدُ بْنُ الْمُسَيَّبِ بْنِ حَزْنٍnindex.php?page=hadith&LINKID=880039أَنَّ جَدَّهُحَزْنًاأَتَى النَّبِيَّ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- فَقَالَ : مَا اسْمُكَ؟ قَالَ :حَزْنٌ. قَالَ : بَلْ أَنْتَسَهْلٌ. قَالَ : يَا رَسُولَ اللَّهِ ، اسْمٌ سَمَّانِي بِهِ أَبَوَايَ وَعُرِفْتُ بِهِ فِي النَّاسِ ، فَسَكَتَ عَنْهُ النَّبِيُّ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ قَالَسَعِيدٌ: فَمَا زِلْنَا تُعْرَفُ الْحُزُونَةُ فِينَا أَهْلَ الْبَيْتِ.[ص:221 ]هَذَا حَدِيثٌ مُرْسَلٌ ، وَمَرَاسِيلُسَعِيدٍمُحْتَجٌّ بِهَا ، لَكِنَّعَلِيَّ بْنَ زَيْدٍلَيْسَ بِالْحُجَّةِ ، وَأَمَّا الْحَدِيثُ فَمَرْوِيٌّ بِإِسْنَادٍ صَحِيحٍ ، مُتَّصِلٍ ، وَلَفْظُهُ :nindex.php?page=hadith&LINKID=880040أَنَّ النَّبِيَّ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- قَالَ لَهُ : مَا اسْمُكَ؟ قَالَ :حَزْنٌ. قَالَ : أَنْتَسَهْلٌ. فَقَالَ لَا أُغَيِّرُ اسْمًا سَمَّانِيهِ أَبِي قَالَسَعِيدٌ: فَمَا زَالَتْ تِلْكَ الْحُزُونَةُ فِينَا بَعْدُ.الْعَطَّافُ بْنُ خَالِدٍ: عَنْأَبِي حَرْمَلَةَ، عَنِابْنِ الْمُسَيَّبِقَالَ : مَا فَاتَتْنِي الصَّلَاةُ فِي جَمَاعَةٍ مُنْذُ أَرْبَعِينَ سَنَةً .nindex.php?page=showalam&ids=16004سُفْيَانُ الثَّوْرِيُّ: عَنْعُثْمَانَ بْنِ حَكِيمٍ، سَمِعْتُnindex.php?page=showalam&ids=15990سَعِيدَ بْنَ الْمُسَيَّبِيَقُولُ : مَا أَذَّنَ الْمُؤَذِّنُ مُنْذُ ثَلَاثِينَ سَنَةً إِلَّا وَأَنَا فِي الْمَسْجِدِ . إِسْنَادُهُ ثَابِتٌ .حَمَّادُ بْنُ زَيْدٍ: حَدَّثَنَايَزِيدُ بْنُ حَازِمٍ، أَنَّnindex.php?page=showalam&ids=15990سَعِيدَ بْنَ الْمُسَيَّبِكَانَ يَسْرُدُ الصَّوْمَ .مِسْعَرٌعَنْسَعِيدِ بْنِ إِبْرَاهِيمَ، سَمِعَابْنَ الْمُسَيَّبِيَقُولُ : مَا أَحَدٌ أَعْلَمُ بِقَضَاءٍ قَضَاهُ رَسُولُ اللَّهِ -صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ- وَلَاأَبُو بَكْرٍ، وَلَاعُمَرُمِنِّي .[ص:222 ]أُسَامَةُ بْنُ زَيْدٍ: عَنْنَافِعٍ، أَنَّابْنَ عُمَرَذَكَرَnindex.php?page=showalam&ids=15990سَعِيدَ بْنَ الْمُسَيَّبِفَقَالَ : هُوَ -وَاللَّهِ- أَحَدُ الْمُفْتِينَ .قَالَnindex.php?page=showalam&ids=12251أَحْمَدُ بْنُ حَنْبَلٍوَغَيْرُ وَاحِدٍ : مُرْسَلَاتُnindex.php?page=showalam&ids=15990سَعِيدِ بْنِ الْمُسَيَّبِصِحَاحٌ .وَقَالَقَتَادَةُ،وَمَكْحُولٌ،nindex.php?page=showalam&ids=12300وَالزُّهْرِيُّ، وَآخَرُونَ ، وَاللَّفْظُلِقَتَادَةَ: مَا رَأَيْتُ أَعْلَمَ مِنْnindex.php?page=showalam&ids=15990سَعِيدِ بْنِ الْمُسَيَّبِ.قَالَnindex.php?page=showalam&ids=16604عَلِيُّ بْنُ الْمَدِينِيِّ: لَا أَعْلَمُ فِي التَّابِعِينَ أَحَدًا أَوْسَعَ عِلْمًا مِنْابْنِ الْمُسَيَّبِ، هُوَ عِنْدِي أَجَلُّ التَّابِعِينَ .عَبْدُ الرَّحْمَنِ بْنُ حَرْمَلَةَ: سَمِعْتُابْنَ الْمُسَيَّبِيَقُولُ : حَجَجْتُ أَرْبَعِينَ حِجَّةً .قَالَيَحْيَى بْنُ سَعِيدٍ الْأَنْصَارِيُّ: كَانَسَعِيدٌيُكْثِرُ أَنْ يَقُولَ فِي مَجْلِسِهِ : اللَّهُمَّ سَلِّمْ سَلِّمْ .مَعْنٌ : سَمِعْتُnindex.php?page=showalam&ids=16867مَالِكًايَقُولُ : قَالَابْنُ الْمُسَيَّبِ: إِنُ كُنْتُ لَأَسِيرُ الْأَيَّامَ وَاللَّيَالِيَ فِي طَلَبِ الْحَدِيثِ الْوَاحِدِ .ابْنُ عُيَيْنَةَ: عَنْإِبْرَاهِيمَ بْنِ طَرِيفٍ، عَنْحُمَيْدِ بْنِ يَعْقُوبَ، سَمِعَnindex.php?page=showalam&ids=15990سَعِيدَ بْنَ الْمُسَيَّبِيَقُولُ : سَمِعْتُ مِنْعُمَرَكَلِمَةً مَا بَقِيَ أَحَدٌ سَمِعَهَا غَيْرِي .أَبُو إِسْحَاقَ الشَّيْبَانِيُّ: عَنْبُكَيْرِ بْنِ الْأَخْنَسِ، عَنْسَعِيدِ بْنِ[ص:223 ]الْمُسَيَّبِ، قَالَ : سَمِعْتُعُمَرَعَلَى الْمِنْبَرِ وَهُوَ يَقُولُ : لَا أَجِدُ أَحَدًا جَامَعَ فَلَمْ يَغْتَسِلْ ، أَنْزَلَ أَوْ لَمْ يُنْزِلْ ، إِلَّا عَاقَبْتُهُ .ابْنُ عُيَيْنَةَ : عَنْيَحْيَى بْنِ سَعِيدٍ، عَنِابْنِ الْمُسَيَّبِ، قَالَ : وُلِدْتُ لِسَنَتَيْنِ مَضَتَا مِنْ خِلَافَةِعُمَرَوَكَانَتْ خِلَافَتُهُ عَشْرَ سِنِينَ وَأَرْبَعَةَ أَشْهُرٍ .']\n"
42
+ ]
43
+ },
44
+ {
45
+ "name": "stderr",
46
+ "output_type": "stream",
47
+ "text": [
48
+ "/tmp/ipykernel_13652/1161671790.py:1: RuntimeWarning: coroutine 'scrape_siyar_alaam_nubala' was never awaited\n",
49
+ " result = await scrape_siyar_alaam_nubala()\n",
50
+ "RuntimeWarning: Enable tracemalloc to get the object allocation traceback\n"
51
  ]
52
  }
53
  ],
54
  "source": [
55
+ "result = await scrape_siyar_alaam_nubala()\n",
56
+ "print(result)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  ]
58
  },
59
  {
60
  "cell_type": "code",
61
  "execution_count": null,
62
+ "id": "9ebfe517",
63
  "metadata": {},
64
  "outputs": [],
65
  "source": []
docs/README_Enhanced_Narrator_Agent.md DELETED
@@ -1,190 +0,0 @@
1
- # Enhanced Narrator Analyzer Agent
2
-
3
- ## Overview
4
-
5
- The Enhanced Narrator Analyzer Agent is an intelligent system that combines multiple data sources to provide comprehensive analysis of hadith narrators. It integrates:
6
-
7
- 1. **Shamela.ws Scraping**: Automatically extracts narrator information from Shamela.ws
8
- 2. **LLM Analysis**: Uses Google's Gemini model for intelligent reasoning and synthesis
9
- 3. **Scholarly Assessment**: Applies traditional hadith criticism methodologies
10
-
11
- ## Key Features
12
-
13
- ### 🔍 Multi-Source Analysis
14
- - **Shamela Data**: Extracts biographical info and scholarly opinions from Shamela.ws
15
- - **LLM Knowledge**: Leverages AI's knowledge of Islamic hadith literature
16
- - **Data Synthesis**: Intelligently combines both sources for comprehensive assessment
17
-
18
- ### 🔗 Chain Analysis
19
- - **Individual Narrator Analysis**: Detailed assessment of each narrator
20
- - **Chain Synthesis**: Overall assessment considering the "weakest link" principle
21
- - **Scholarly Methodology**: Applies traditional hadith criticism standards
22
-
23
- ### 📊 Structured Output
24
- - **Reliability Grades**: Thiqah, Saduq, Da'if, Matruk, Majhul
25
- - **Confidence Levels**: High, Medium, Low
26
- - **Detailed Reasoning**: Comprehensive explanations for all assessments
27
- - **Practical Recommendations**: Guidance for hadith scholars
28
-
29
- ## API Endpoints
30
-
31
- ### 1. Enhanced Narrator Analysis
32
- ```http
33
- POST /api/v1/analyze-narrator
34
- ```
35
- Analyzes a single narrator using both Shamela data and LLM knowledge.
36
-
37
- **Request:**
38
- ```json
39
- {
40
- "narrator_name": "زرارة بن أعين"
41
- }
42
- ```
43
-
44
- **Response:**
45
- ```json
46
- {
47
- "narrator_name": "زرارة بن أعين",
48
- "reliability_grade": "Thiqah",
49
- "confidence_level": "High",
50
- "reasoning": "Detailed analysis combining Shamela data and scholarly knowledge...",
51
- "scholarly_consensus": "Analysis of what scholars have said...",
52
- "biographical_info": "Basic biographical information...",
53
- "recommendation": "Practical guidance for hadith scholars...",
54
- "success": true,
55
- "message": "Analysis completed using Shamela data (3 scholars) + LLM knowledge"
56
- }
57
- ```
58
-
59
- ### 2. Narrator Chain Analysis
60
- ```http
61
- POST /api/v1/analyze-narrator-chain
62
- ```
63
- Analyzes a complete chain of narrators with synthesis.
64
-
65
- **Request:**
66
- ```json
67
- ["زرارة بن أعين", "أبو جعفر الباقر", "جابر بن عبد الله"]
68
- ```
69
-
70
- **Response:**
71
- ```json
72
- {
73
- "chain": ["narrator1", "narrator2", "narrator3"],
74
- "individual_analyses": {
75
- "narrator1": { "detailed analysis..." },
76
- "narrator2": { "detailed analysis..." },
77
- "narrator3": { "detailed analysis..." }
78
- },
79
- "chain_synthesis": {
80
- "overall_assessment": "Comprehensive chain evaluation...",
81
- "success": true
82
- },
83
- "metadata": {
84
- "total_narrators": 3,
85
- "successful_analyses": 3,
86
- "analysis_method": "Enhanced agent with Shamela.ws + LLM"
87
- }
88
- }
89
- ```
90
-
91
- ### 3. Complete Hadith Analysis
92
- ```http
93
- POST /api/v1/extract-and-analyze
94
- ```
95
- Complete workflow: extract narrators from hadith text and analyze the chain.
96
-
97
- **Request:**
98
- ```json
99
- {
100
- "hadith_text": "حدثنا زرارة بن أعين عن أبي جعفر الباقر..."
101
- }
102
- ```
103
-
104
- ## Technical Architecture
105
-
106
- ### Data Flow
107
- 1. **Input**: Narrator name or hadith text
108
- 2. **Shamela Scraping**: Automated extraction of narrator data
109
- 3. **Data Formatting**: Structure Shamela data for LLM consumption
110
- 4. **LLM Analysis**: Intelligent reasoning combining all sources
111
- 5. **Output**: Structured, comprehensive assessment
112
-
113
- ### Integration Components
114
-
115
- #### ShamelaNarratorExtractor
116
- - Searches Google for Shamela.ws narrator pages
117
- - Extracts biographical information and scholarly critiques
118
- - Provides structured data with quality metadata
119
-
120
- #### Enhanced LLM Service
121
- - Formats Shamela data for optimal LLM understanding
122
- - Uses sophisticated prompts for scholarly analysis
123
- - Applies traditional hadith criticism methodologies
124
-
125
- #### Chain Analysis Features
126
- - Individual narrator assessment
127
- - Chain-level synthesis considering cumulative effects
128
- - Practical recommendations for hadith acceptance
129
-
130
- ## Scholarly Methodology
131
-
132
- ### Reliability Grades
133
- - **Thiqah (ثقة)**: Trustworthy - strong consensus of reliability
134
- - **Saduq (صدوق)**: Truthful - generally reliable with minor reservations
135
- - **Da'if (ضعيف)**: Weak - significant concerns about reliability
136
- - **Matruk (متروك)**: Abandoned - severe weakness, narrations rejected
137
- - **Majhul (مجهول)**: Unknown - insufficient reliable information
138
-
139
- ### Analysis Framework
140
- 1. **Prioritize Classical Scholars**: Ibn Hajar, Dhahabi, Ibn Hibban, etc.
141
- 2. **Consider Scholarly Consensus**: Weight of agreement among authorities
142
- 3. **Balance Criticism vs Praise**: Appropriate evaluation of mixed opinions
143
- 4. **Historical Context**: Account for time period and scholarly methodology
144
- 5. **Practical Application**: Provide actionable guidance for hadith scholars
145
-
146
- ### Confidence Assessment
147
- - **High**: Strong evidence from multiple reliable sources
148
- - **Medium**: Good evidence with some limitations or disagreement
149
- - **Low**: Limited evidence or significant uncertainty
150
-
151
- ## Usage Examples
152
-
153
- ### Testing the Enhanced Agent
154
- ```bash
155
- python test_enhanced_narrator_agent.py
156
- ```
157
-
158
- This will run comprehensive tests demonstrating:
159
- - Single narrator analysis with Shamela integration
160
- - Chain analysis with synthesis
161
- - Unknown narrator handling
162
- - Error handling and edge cases
163
-
164
- ### API Integration
165
- The enhanced analyzer integrates seamlessly with existing FastAPI endpoints and maintains backward compatibility while adding powerful new features.
166
-
167
- ## Benefits
168
-
169
- ### For Researchers
170
- - **Comprehensive Data**: Combines multiple authoritative sources
171
- - **Time Saving**: Automated data gathering and analysis
172
- - **Scholarly Rigor**: Applies traditional methodologies systematically
173
-
174
- ### For Developers
175
- - **Structured Output**: Easy integration with other systems
176
- - **Scalable**: Can analyze individual narrators or complete chains
177
- - **Reliable**: Robust error handling and quality metadata
178
-
179
- ### For Students
180
- - **Educational**: Detailed reasoning explains traditional methodology
181
- - **Accessible**: Converts complex scholarly assessments into clear guidance
182
- - **Comprehensive**: Provides both specific and general insights
183
-
184
- ## Future Enhancements
185
-
186
- 1. **Additional Sources**: Integration with more classical texts and databases
187
- 2. **Comparative Analysis**: Cross-referencing multiple narrator evaluation works
188
- 3. **Historical Timeline**: Temporal analysis of narrator relationships
189
- 4. **Visualization**: Graphical representation of narrator chains and assessments
190
- 5. **Caching**: Performance optimization for frequently analyzed narrators
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/README_ShamelaNarratorExtractor.md DELETED
@@ -1,246 +0,0 @@
1
- # ShamelaNarratorExtractor Documentation
2
-
3
- ## Overview
4
-
5
- The `ShamelaNarratorExtractor` class is a comprehensive tool for extracting narrator information from Shamela.ws (المكتبة الشاملة) that can be easily integrated into LangGraph workflows.
6
-
7
- ## Features
8
-
9
- - **Automated Search**: Searches Google for narrator pages on Shamela.ws
10
- - **Structured Extraction**: Extracts biographical information and scholarly critiques
11
- - **Type Safety**: Uses dataclasses for type-safe data structures
12
- - **LangGraph Ready**: Designed to work seamlessly with LangGraph nodes
13
- - **Error Handling**: Robust error handling and reporting
14
- - **Backwards Compatibility**: Provides legacy function support
15
-
16
- ## Data Structures
17
-
18
- ### NarratorComment
19
- ```python
20
- @dataclass
21
- class NarratorComment:
22
- text: str # The comment text
23
- highlighted: List[str] # Highlighted/bold text in the comment
24
- ```
25
-
26
- ### ScholarCritique
27
- ```python
28
- @dataclass
29
- class ScholarCritique:
30
- scholar: str # Name of the scholar
31
- comments: List[NarratorComment] # List of comments from this scholar
32
- ```
33
-
34
- ### NarratorInfo
35
- ```python
36
- @dataclass
37
- class NarratorInfo:
38
- narrator_name: Optional[str] # Name of the narrator
39
- biographical_info: Dict[str, str] # Biographical information
40
- scholarly_critique: List[ScholarCritique] # Scholarly critiques
41
- extraction_metadata: Dict[str, Any] # Extraction statistics and metadata
42
- ```
43
-
44
- ## Main Class: ShamelaNarratorExtractor
45
-
46
- ### Constructor
47
- ```python
48
- extractor = ShamelaNarratorExtractor()
49
- ```
50
-
51
- No parameters required. Initializes the extractor with default settings.
52
-
53
- ### Primary Method: search_and_extract()
54
-
55
- ```python
56
- def search_and_extract(self, narrator_name: str) -> NarratorInfo:
57
- """
58
- Main method for LangGraph nodes: searches for narrator and extracts information.
59
-
60
- Args:
61
- narrator_name: Name of the narrator to search for
62
-
63
- Returns:
64
- NarratorInfo object containing all extracted information
65
- """
66
- ```
67
-
68
- **Example Usage:**
69
- ```python
70
- extractor = ShamelaNarratorExtractor()
71
- narrator_info = extractor.search_and_extract("الزهري")
72
-
73
- print(f"Narrator: {narrator_info.narrator_name}")
74
- print(f"Biographical fields: {len(narrator_info.biographical_info)}")
75
- print(f"Number of scholars: {len(narrator_info.scholarly_critique)}")
76
- ```
77
-
78
- ### Utility Method: to_dict()
79
-
80
- ```python
81
- def to_dict(self, narrator_info: NarratorInfo) -> Dict[str, Any]:
82
- """Convert NarratorInfo object to dictionary for backwards compatibility."""
83
- ```
84
-
85
- Converts the structured `NarratorInfo` object to a dictionary format for easier serialization or backwards compatibility.
86
-
87
- ## LangGraph Integration
88
-
89
- ### Basic Node Implementation
90
-
91
- ```python
92
- def narrator_extraction_node(state: GraphState) -> GraphState:
93
- """LangGraph node that extracts narrator information."""
94
- try:
95
- extractor = ShamelaNarratorExtractor()
96
- narrator_name = state.get("narrator_name", "")
97
-
98
- if not narrator_name:
99
- return {**state, "error": "No narrator name provided"}
100
-
101
- narrator_info = extractor.search_and_extract(narrator_name)
102
- narrator_dict = extractor.to_dict(narrator_info)
103
-
104
- return {
105
- **state,
106
- "narrator_info": narrator_dict,
107
- "processed": True
108
- }
109
- except Exception as e:
110
- return {**state, "error": str(e)}
111
- ```
112
-
113
- ### State Schema Example
114
-
115
- ```python
116
- class GraphState(TypedDict):
117
- narrator_name: str
118
- narrator_info: Dict[str, Any]
119
- error: str
120
- processed: bool
121
- ```
122
-
123
- ## Error Handling
124
-
125
- The class provides comprehensive error handling:
126
-
127
- 1. **Search Errors**: When no Shamela.ws pages are found
128
- 2. **Network Errors**: When requests fail
129
- 3. **Parsing Errors**: When HTML structure is unexpected
130
- 4. **General Errors**: Catches all other exceptions
131
-
132
- Errors are reported in the `extraction_metadata` field:
133
-
134
- ```python
135
- narrator_info = extractor.search_and_extract("invalid_name")
136
- if "error" in narrator_info.extraction_metadata:
137
- print(f"Error: {narrator_info.extraction_metadata['error']}")
138
- ```
139
-
140
- ## Extracted Information Types
141
-
142
- ### Biographical Information
143
- - **الاسم** (Name)
144
- - **الكنية** (Kunya/Nickname)
145
- - **النسب** (Lineage)
146
- - **بلد** (Country/Place)
147
- - **تاريخ** (Date/Timeline)
148
- - **طبقة** (Generation/Class)
149
- - **علاقات** (Relationships)
150
-
151
- ### Scholarly Critique
152
- - **Scholar Names**: Names of the critics (العجلي، ابن حبان، النسائي، etc.)
153
- - **Comments**: Their evaluations and comments
154
- - **Highlighted Terms**: Important terms marked in the original text
155
-
156
- ### Metadata
157
- - **total_scholars**: Number of different scholars who commented
158
- - **biographical_fields**: Number of biographical data points found
159
- - **has_critique_section**: Whether scholarly critique section exists
160
- - **total_comments**: Total number of individual comments
161
-
162
- ## Performance Considerations
163
-
164
- - **Caching**: Consider implementing caching for repeated searches
165
- - **Rate Limiting**: Google search has rate limits; implement delays if needed
166
- - **Timeout**: Default timeout is 10 seconds for HTTP requests
167
- - **Memory**: Large HTML pages may use significant memory
168
-
169
- ## Legacy Compatibility
170
-
171
- The following legacy functions are maintained for backwards compatibility:
172
-
173
- ```python
174
- # Legacy functions (use ShamelaNarratorExtractor instead)
175
- extract_narrator_info(html_content: str) -> Dict[str, Any]
176
- clean_biographical_info(bio_info: Dict[str, str]) -> Dict[str, str]
177
- extract_narrator_info_enhanced(html_content: str) -> Dict[str, Any]
178
- get_shamela_content(query: str) -> str
179
- ```
180
-
181
- ## Dependencies
182
-
183
- ```bash
184
- pip install beautifulsoup4 requests googlesearch-python
185
- ```
186
-
187
- ## Example Complete Workflow
188
-
189
- ```python
190
- from scrape_shamela import ShamelaNarratorExtractor
191
-
192
- # Initialize extractor
193
- extractor = ShamelaNarratorExtractor()
194
-
195
- # Extract information
196
- narrator_info = extractor.search_and_extract("أبو هريرة")
197
-
198
- # Check for errors
199
- if "error" in narrator_info.extraction_metadata:
200
- print(f"Error: {narrator_info.extraction_metadata['error']}")
201
- else:
202
- # Access structured data
203
- print(f"Name: {narrator_info.narrator_name}")
204
-
205
- # Biographical info
206
- for key, value in narrator_info.biographical_info.items():
207
- print(f"{key}: {value}")
208
-
209
- # Scholarly critiques
210
- for critique in narrator_info.scholarly_critique:
211
- print(f"Scholar: {critique.scholar}")
212
- for comment in critique.comments:
213
- print(f" Comment: {comment.text}")
214
- if comment.highlighted:
215
- print(f" Highlighted: {comment.highlighted}")
216
-
217
- # Convert to dict if needed
218
- narrator_dict = extractor.to_dict(narrator_info)
219
- ```
220
-
221
- ## Best Practices
222
-
223
- 1. **Always check for errors** in the extraction_metadata
224
- 2. **Use type hints** when working with the data structures
225
- 3. **Handle network timeouts** gracefully
226
- 4. **Cache results** when possible to avoid repeated searches
227
- 5. **Validate narrator names** before searching
228
- 6. **Use the structured objects** rather than legacy dictionary format when possible
229
-
230
- ## Troubleshooting
231
-
232
- ### Common Issues
233
-
234
- 1. **No search results**: Verify narrator name spelling and existence on Shamela.ws
235
- 2. **Network timeouts**: Check internet connection and consider increasing timeout
236
- 3. **Parsing errors**: Shamela.ws may have changed their HTML structure
237
- 4. **Rate limiting**: Implement delays between multiple searches
238
-
239
- ### Debug Mode
240
-
241
- To enable debugging, modify the search method to print more information:
242
-
243
- ```python
244
- # Add this after search_results in _get_shamela_content method
245
- print(f"Found {len(search_results)} results: {search_results}")
246
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_api.py → tests/test_api.py RENAMED
File without changes
test_enhanced_narrator_agent.py → tests/test_enhanced_narrator_agent.py RENAMED
@@ -12,7 +12,7 @@ from pathlib import Path
12
  project_root = Path(__file__).parent
13
  sys.path.insert(0, str(project_root))
14
 
15
- from services import LLMService
16
  from pprint import pprint
17
 
18
 
 
12
  project_root = Path(__file__).parent
13
  sys.path.insert(0, str(project_root))
14
 
15
+ from app.agent.services import LLMService
16
  from pprint import pprint
17
 
18