-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcarfax_webapp.py
More file actions
316 lines (255 loc) · 11.1 KB
/
Copy pathcarfax_webapp.py
File metadata and controls
316 lines (255 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
"""
Carfax VIN Scraper Web App
تطبيق ويب لاستخراج معلومات VIN من Carfax
"""
import streamlit as st
import json
import time
import re
from datetime import datetime
import sys
import os
import threading
# إضافة المسار الحالي للـ sys.path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
from vin_scraper_advanced import scrape_vin_advanced
except ImportError as e:
st.error(f"❌ خطأ في استيراد vin_scraper_advanced: {str(e)}")
st.stop()
# إعداد الصفحة
st.set_page_config(
page_title="Carfax VIN Scraper",
page_icon="🚗",
layout="wide",
initial_sidebar_state="expanded"
)
# العنوان الرئيسي
st.title("🚗 Carfax VIN Scraper Web App")
st.markdown("---")
# Sidebar للإعدادات والمعلومات
with st.sidebar:
st.header("⚙️ الإعدادات")
st.info("💡 أدخل VIN number واضغط على 'استخراج المعلومات'")
st.markdown("---")
st.subheader("ℹ️ معلومات")
st.markdown("""
### كيفية الاستخدام:
1. أدخل VIN number في الحقل الرئيسي
2. اضغط على 'استخراج المعلومات'
3. انتظر حتى يتم استخراج البيانات
4. راجع النتائج في الصفحة
### ملاحظات:
- VIN يجب أن يكون 17 حرف
- قد يستغرق الاستخراج بضع دقائق
- النتائج تُحفظ تلقائياً في ملفات JSON و HTML
""")
st.markdown("---")
if st.button("🔄 تحديث الصفحة"):
st.rerun()
# الحالة الرئيسية
if 'scraping_in_progress' not in st.session_state:
st.session_state.scraping_in_progress = False
if 'last_results' not in st.session_state:
st.session_state.last_results = None
if 'scraping_history' not in st.session_state:
st.session_state.scraping_history = []
if 'current_vin' not in st.session_state:
st.session_state.current_vin = ""
# قسم إدخال VIN
st.header("📝 إدخال VIN Number")
with st.form("vin_form", clear_on_submit=False):
col1, col2 = st.columns([3, 1])
with col1:
vin_number = st.text_input(
"VIN Number",
placeholder="أدخل VIN number هنا (مثال: 5FNYG1H72SB138083)",
key="vin_input",
disabled=st.session_state.scraping_in_progress
)
# حفظ VIN في session state
if vin_number:
st.session_state.current_vin = vin_number
with col2:
scrape_button = st.form_submit_button(
"🔍 استخراج المعلومات",
type="primary",
use_container_width=True,
disabled=st.session_state.scraping_in_progress
)
# التحقق من صحة VIN
if vin_number and len(vin_number) != 17:
st.warning("⚠️ VIN يجب أن يكون 17 حرف")
# قسم الاستخراج
if scrape_button and vin_number and len(vin_number) == 17:
st.session_state.scraping_in_progress = True
st.session_state.current_vin = vin_number
# استخدام placeholder لتحديث الحالة
status_placeholder = st.empty()
with status_placeholder.container():
st.info(f"🔄 جاري استخراج معلومات VIN: {vin_number}... قد يستغرق هذا بضع دقائق")
progress_bar = st.progress(0)
status_text = st.empty()
try:
# استدعاء دالة الاستخراج (بدون انتظار input، مع headless mode)
status_text.text("جاري فتح المتصفح...")
progress_bar.progress(10)
results = scrape_vin_advanced(vin_number, keep_browser_open_for_inspection=False, headless=True)
progress_bar.progress(100)
status_text.text("✓ تم الاستخراج بنجاح!")
# حفظ النتائج في session state
st.session_state.last_results = results
st.session_state.scraping_history.append({
'vin': vin_number,
'timestamp': datetime.now().isoformat(),
'success': results.get('success', False)
})
st.session_state.scraping_in_progress = False
status_placeholder.empty()
st.success("✅ تم استخراج المعلومات بنجاح!")
time.sleep(1)
st.rerun()
except Exception as e:
st.session_state.scraping_in_progress = False
status_placeholder.empty()
st.error(f"❌ حدث خطأ أثناء الاستخراج: {str(e)}")
import traceback
with st.expander("تفاصيل الخطأ"):
st.code(traceback.format_exc())
# عرض النتائج
if st.session_state.last_results:
results = st.session_state.last_results
st.header("📊 النتائج")
st.markdown("---")
# معلومات أساسية
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("VIN Number", results.get('vin', 'N/A'))
with col2:
success_status = "✅ نجح" if results.get('success', False) else "⚠️ فشل"
st.metric("الحالة", success_status)
with col3:
timestamp = results.get('timestamp', 'N/A')
if timestamp != 'N/A':
try:
dt = datetime.fromisoformat(timestamp)
st.metric("التاريخ والوقت", dt.strftime("%Y-%m-%d %H:%M"))
except:
st.metric("التاريخ والوقت", timestamp)
else:
st.metric("التاريخ والوقت", "N/A")
with col4:
url = results.get('url', 'N/A')
if url != 'N/A' and len(url) > 40:
url_display = url[:37] + "..."
else:
url_display = url
st.metric("URL", url_display)
st.markdown("---")
# معلومات الصفحة
st.subheader("🔗 معلومات الصفحة")
col1, col2 = st.columns(2)
with col1:
st.text_area("URL الكامل", results.get('url', 'N/A'), height=100, disabled=True)
with col2:
st.text_area("عنوان الصفحة", results.get('title', 'N/A'), height=100, disabled=True)
# محتوى الصفحة
st.subheader("📄 محتوى الصفحة")
page_text = results.get('page_text', '')
if page_text:
# البحث عن معلومات مهمة في النص
st.markdown("### 🔍 معلومات مستخرجة من النص:")
# البحث عن Year, Make, Model
year_match = re.search(r'\b(19|20)\d{2}\b', page_text)
make_model_match = re.search(r'(\d{4})\s+([A-Za-z]+)\s+([A-Za-z\s]+)', page_text)
info_cols = st.columns(4)
if year_match:
with info_cols[0]:
st.metric("السنة", year_match.group())
if make_model_match:
with info_cols[1]:
st.metric("الماركة", make_model_match.group(2))
with info_cols[2]:
st.metric("الموديل", make_model_match.group(3).strip())
# البحث عن Mileage
mileage_match = re.search(r'(\d{1,3}(?:,\d{3})*)\s*(?:miles|mile|mi|كم)', page_text, re.IGNORECASE)
if mileage_match:
with info_cols[3]:
st.metric("المسافة المقطوعة", mileage_match.group(1))
st.markdown("---")
# عرض النص الكامل
with st.expander("📋 عرض النص الكامل (أول 10000 حرف)"):
st.text_area("", page_text[:10000], height=400, disabled=True)
else:
st.warning("⚠️ لا يوجد نص في الصفحة")
# Network Requests
if 'network_responses' in results and results['network_responses']:
st.subheader("🌐 Network Requests")
network_data = results['network_responses']
st.info(f"تم تسجيل {len(network_data)} طلب من الشبكة")
# عرض API calls المهمة
api_calls = [r for r in network_data if 'api' in r.get('url', '').lower() or 'vhr' in r.get('url', '').lower()]
if api_calls:
st.markdown("### 🔗 API Calls المهمة:")
for i, call in enumerate(api_calls[:10], 1): # أول 10 API calls
status = call.get('status', 'N/A')
url = call.get('url', 'N/A')
method = call.get('method', 'N/A')
# تحديد لون حسب Status
if status == 200:
status_color = "🟢"
elif status == 403:
status_color = "🔴"
elif status >= 400:
status_color = "🟡"
else:
status_color = "⚪"
st.markdown(f"{status_color} **{i}.** `{method}` {status} - {url[:80]}...")
with st.expander("📋 عرض جميع Network Requests"):
st.json(network_data)
# الملفات المحفوظة
st.subheader("💾 الملفات المحفوظة")
col1, col2 = st.columns(2)
with col1:
if 'html_saved' in results and results['html_saved']:
html_file = results['html_saved']
if os.path.exists(html_file):
with open(html_file, 'r', encoding='utf-8') as f:
html_content = f.read()
st.download_button(
label="📥 تحميل HTML",
data=html_content,
file_name=html_file,
mime="text/html"
)
else:
st.warning(f"⚠️ الملف غير موجود: {html_file}")
with col2:
json_data = json.dumps(results, indent=2, ensure_ascii=False)
st.download_button(
label="📥 تحميل JSON",
data=json_data,
file_name=f"carfax_vin_{results.get('vin', 'unknown')}_{int(time.time())}.json",
mime="application/json"
)
# سجل البحث
if st.session_state.scraping_history:
st.subheader("📜 سجل البحث")
history_df_data = []
for item in st.session_state.scraping_history[-10:]: # آخر 10 عمليات
history_df_data.append({
'VIN': item['vin'],
'التاريخ': item['timestamp'][:19],
'الحالة': '✅ نجح' if item['success'] else '⚠️ فشل'
})
if history_df_data:
import pandas as pd
history_df = pd.DataFrame(history_df_data)
st.dataframe(history_df, use_container_width=True, hide_index=True)
# Footer
st.markdown("---")
st.markdown("""
<div style='text-align: center; color: gray;'>
<p>Carfax VIN Scraper Web App | Made with ❤️</p>
</div>
""", unsafe_allow_html=True)