TeanShow commited on
Commit
071f272
·
verified ·
1 Parent(s): dee8677

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +165 -0
  2. packages.txt +9 -0
  3. requirements.txt +6 -3
app.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import asyncio
3
+ import streamlit as st
4
+ from bs4 import BeautifulSoup
5
+ from openai import OpenAI
6
+ import json
7
+ import pandas as pd
8
+ import re
9
+
10
+
11
+ from playwright.sync_api import sync_playwright
12
+
13
+ # ==========================================
14
+ # 🎨 НАСТРОЙКИ СТРАНИЦЫ И КАСТОМНЫЙ ДИЗАЙН
15
+ # ==========================================
16
+ st.set_page_config(page_title="AI Scraper Pro", page_icon="🕷️", layout="wide", initial_sidebar_state="expanded")
17
+
18
+ st.markdown("""
19
+ <style>
20
+ #MainMenu {visibility: hidden;}
21
+ footer {visibility: hidden;}
22
+ header {visibility: hidden;}
23
+ .stButton>button {
24
+ border-radius: 8px;
25
+ height: 3em;
26
+ font-weight: bold;
27
+ transition: 0.3s;
28
+ }
29
+ </style>
30
+ """, unsafe_allow_html=True)
31
+
32
+
33
+ # ==========================================
34
+ # 🧠 ЛОГИКА ПАРСИНГА (PLAYWRIGHT + DEEPSEEK)
35
+ # ==========================================
36
+ def fetch_and_clean_page(url: str) -> str:
37
+ import sys
38
+ import asyncio
39
+
40
+ # 1. ЖЕСТКИЙ ФИКС ДЛЯ WINDOWS (Умеет запускать подпроцессы)
41
+ if sys.platform == 'win32':
42
+ asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
43
+
44
+ # 2. Создаем новый цикл для потока Streamlit
45
+ loop = asyncio.new_event_loop()
46
+ asyncio.set_event_loop(loop)
47
+
48
+ with sync_playwright() as p:
49
+ browser = p.chromium.launch(headless=True)
50
+ # Маскируемся под обычный Chrome на Windows
51
+ context = browser.new_context(
52
+ user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
53
+ viewport={'width': 1920, 'height': 1080}
54
+ )
55
+ page = context.new_page()
56
+ try:
57
+ # Заходим на сайт и даем время прогрузиться
58
+ page.goto(url, wait_until="domcontentloaded", timeout=30000)
59
+ page.wait_for_timeout(3000)
60
+ html = page.content()
61
+ except Exception as e:
62
+ st.error(f"❌ Ошибка загрузки страницы браузером: {e}")
63
+ return ""
64
+ finally:
65
+ browser.close()
66
+
67
+ # Сжимаем HTML
68
+ soup = BeautifulSoup(html, 'html.parser')
69
+ for element in soup(["script", "style", "noscript", "svg", "nav", "footer", "header"]):
70
+ element.decompose()
71
+
72
+ clean_text = soup.get_text(separator=' | ', strip=True)
73
+ return clean_text[:15000]
74
+
75
+ def extract_data_with_ai(text: str, user_request: str, api_key: str) -> list:
76
+ """Отправляет сжатый текст в нейросеть для извлечения JSON."""
77
+ client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com")
78
+
79
+ system_prompt = """Ты строгий API-парсер. Верни СТРОГО массив JSON объектов `[{"название": "...", "цена": "..."}]`. Никакого мусора, только валидный JSON."""
80
+ user_prompt = f"Запрос: {user_request}\n\nТекст:\n{text}"
81
+
82
+ try:
83
+ response = client.chat.completions.create(
84
+ model="deepseek-chat",
85
+ messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}],
86
+ temperature=0.0,
87
+ response_format={"type": "json_object"}
88
+ )
89
+
90
+ result_text = response.choices[0].message.content.strip()
91
+ result_text = re.sub(r'^```json\s*', '', result_text)
92
+ result_text = re.sub(r'\s*```$', '', result_text)
93
+
94
+ data = json.loads(result_text)
95
+ if isinstance(data, dict):
96
+ for key, val in data.items():
97
+ if isinstance(val, list): return val
98
+ return [data]
99
+ return data if isinstance(data, list) else []
100
+ except Exception as e:
101
+ st.error(f"❌ Ошибка ИИ (проверь API-ключ): {e}")
102
+ return []
103
+
104
+
105
+ # ==========================================
106
+ # 🖥️ ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС (UI)
107
+ # ==========================================
108
+
109
+ # --- БОКОВАЯ ПАНЕЛЬ ---
110
+ with st.sidebar:
111
+ st.image("https://cdn-icons-png.flaticon.com/512/2103/2103837.png", width=80)
112
+ st.title("⚙️ Настройки")
113
+ st.markdown("Для работы парсера нужен API-ключ DeepSeek.")
114
+ api_key_input = st.text_input("DeepSeek API Key", type="password", placeholder="sk-...")
115
+ st.divider()
116
+ st.markdown("### 💡 Как использовать:")
117
+ st.markdown("1. Вставь ссылку на любой магазин.\n2. Напиши, что именно нужно найти.\n3. Скачай готовую таблицу!")
118
+ st.caption("Создано тобой © 2026")
119
+
120
+ # --- ГЛАВНЫЙ ЭКРАН ---
121
+ st.title("🕷️ Smart AI Web Scraper")
122
+ st.markdown("Извлекай структурированные данные с **любого сайта**, обходя блокировки.")
123
+
124
+ with st.container():
125
+ col1, col2 = st.columns([1, 1])
126
+ with col1:
127
+ url_input = st.text_input("🌐 Ссылка на сайт", placeholder="https://...")
128
+ with col2:
129
+ query_input = st.text_input("🎯 Что ищем?", placeholder="Например: Собери 10 товаров, названия и цены")
130
+
131
+ submit_button = st.button("🚀 ЗАПУСТИТЬ ПАРСИНГ", type="primary", use_container_width=True)
132
+
133
+ if submit_button:
134
+ if not api_key_input:
135
+ st.warning("⚠️ Пожалуйста, введи API-ключ DeepSeek в боковой панели слева!")
136
+ elif not url_input or not query_input:
137
+ st.warning("⚠️ Заполни поля ссылки и запроса!")
138
+ else:
139
+ with st.status("Идет магия парсинга...", expanded=True) as status:
140
+ st.write("🕵️‍♂️ Открываем невидимый браузер и обходим защиту...")
141
+ text = fetch_and_clean_page(url_input)
142
+
143
+ if text:
144
+ st.write("🧠 ИИ анализирует текст и собирает JSON...")
145
+ data = extract_data_with_ai(text, query_input, api_key_input)
146
+
147
+ if data:
148
+ status.update(label="✅ Данные успешно собраны!", state="complete", expanded=False)
149
+ st.success("Ура! ИИ успешно структурировал информацию.")
150
+
151
+ df = pd.DataFrame(data)
152
+ st.dataframe(df, use_container_width=True)
153
+
154
+ st.divider()
155
+ col_csv, col_json = st.columns(2)
156
+ with col_json:
157
+ json_str = json.dumps(data, ensure_ascii=False, indent=4)
158
+ st.download_button("📥 Скачать JSON", data=json_str, file_name="parsed.json",
159
+ mime="application/json", use_container_width=True)
160
+ with col_csv:
161
+ csv_str = df.to_csv(index=False).encode('utf-8')
162
+ st.download_button("📊 Скачать CSV", data=csv_str, file_name="parsed.csv", mime="text/csv",
163
+ use_container_width=True)
164
+ else:
165
+ status.update(label="❌ ИИ не нашел данные", state="error")
packages.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ libgconf-2-4
2
+ libatk1.0-0
3
+ libatk-bridge2.0-0
4
+ libgdk-pixbuf2.0-0
5
+ libgtk-3-0
6
+ libgbm-dev
7
+ libnss3-dev
8
+ libxss-dev
9
+ libasound2
requirements.txt CHANGED
@@ -1,3 +1,6 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
1
+ streamlit>=1.28.0
2
+ cloudscraper>=1.2.71
3
+ beautifulsoup4>=4.12.0
4
+ pandas>=2.0.0
5
+ lxml>=4.9.0
6
+ html5lib>=1.1