🚀 Full project sync: Hotels RAG & Audit System
✨ Major Features: - Complete RAG system for hotel website analysis - Hybrid audit with BGE-M3 embeddings + Natasha NER - Universal horizontal Excel reports with dashboards - Multi-region processing (SPb, Orel, Chukotka, Kamchatka) 📊 Completed Regions: - Орловская область: 100% (36/36) - Чукотский АО: 100% (4/4) - г. Санкт-Петербург: 93% (893/960) - Камчатский край: 87% (89/102) 🔧 Infrastructure: - PostgreSQL with pgvector extension - BGE-M3 embeddings API - Browserless for web scraping - N8N workflows for automation - S3/Nextcloud file storage 📝 Documentation: - Complete DB schemas - API documentation - Setup guides - Status reports
This commit is contained in:
158
test_browserless_scrape.py
Normal file
158
test_browserless_scrape.py
Normal file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Тест Browserless Scrape API для сравнения качества с регулярками
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import psycopg2
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from urllib.parse import unquote
|
||||
import re
|
||||
|
||||
# Конфигурация БД
|
||||
DB_CONFIG = {
|
||||
'host': '147.45.189.234',
|
||||
'port': 5432,
|
||||
'database': 'default_db',
|
||||
'user': 'gen_user',
|
||||
'password': unquote('2~~9_%5EkVsU%3F2%5CS')
|
||||
}
|
||||
|
||||
# Browserless API
|
||||
BROWSERLESS_URL = "http://147.45.146.17:3000/function?token=9ahhnpjkchxtcho9"
|
||||
|
||||
def get_html_from_db():
|
||||
"""Получаем HTML из БД для тестирования"""
|
||||
conn = psycopg2.connect(**DB_CONFIG, cursor_factory=RealDictCursor)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
SELECT html, h.full_name
|
||||
FROM hotel_website_raw hwr
|
||||
INNER JOIN hotel_main h ON h.id = hwr.hotel_id
|
||||
WHERE h.region_name = 'г. Санкт-Петербург'
|
||||
AND hwr.html IS NOT NULL
|
||||
LIMIT 1
|
||||
""")
|
||||
|
||||
result = cur.fetchone()
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
return result['html'], result['full_name']
|
||||
|
||||
def clean_with_regex(html):
|
||||
"""Очистка HTML регулярками (текущий метод)"""
|
||||
# Удаляем script и style теги
|
||||
text = re.sub(r'<script[^>]*>.*?</script>', ' ', html, flags=re.DOTALL | re.IGNORECASE)
|
||||
text = re.sub(r'<style[^>]*>.*?</style>', ' ', text, flags=re.DOTALL | re.IGNORECASE)
|
||||
# Удаляем все HTML теги
|
||||
text = re.sub(r'<[^>]+>', ' ', text)
|
||||
# Декодируем HTML entities
|
||||
import html as html_module
|
||||
text = html_module.unescape(text)
|
||||
# Убираем лишние пробелы
|
||||
text = re.sub(r'\s+', ' ', text).strip()
|
||||
|
||||
return text
|
||||
|
||||
def clean_with_browserless_scrape(html):
|
||||
"""Очистка HTML через Browserless Function API"""
|
||||
|
||||
# JavaScript функция для извлечения текста
|
||||
scrape_function = """
|
||||
export default async function ({ page, context }) {
|
||||
const html = context.html;
|
||||
|
||||
// Устанавливаем HTML в страницу
|
||||
await page.setContent(html);
|
||||
|
||||
// Извлекаем весь текст
|
||||
const text = await page.evaluate(() => {
|
||||
// Удаляем script и style элементы
|
||||
const scripts = document.querySelectorAll('script, style');
|
||||
scripts.forEach(el => el.remove());
|
||||
|
||||
// Получаем весь текст
|
||||
return document.body.innerText || document.body.textContent || '';
|
||||
});
|
||||
|
||||
return {
|
||||
text: text,
|
||||
length: text.length
|
||||
};
|
||||
}
|
||||
"""
|
||||
|
||||
payload = {
|
||||
"code": scrape_function,
|
||||
"context": {"html": html}
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(BROWSERLESS_URL, json=payload, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result and 'text' in result:
|
||||
return result['text']
|
||||
return ""
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка Browserless API: {e}")
|
||||
return ""
|
||||
|
||||
def compare_methods():
|
||||
"""Сравниваем оба метода"""
|
||||
print("🔍 Получаем HTML из БД...")
|
||||
html, hotel_name = get_html_from_db()
|
||||
print(f"📄 Отель: {hotel_name}")
|
||||
print(f"📊 Размер HTML: {len(html):,} символов")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("🧹 МЕТОД 1: РЕГУЛЯРКИ")
|
||||
print("="*60)
|
||||
|
||||
regex_text = clean_with_regex(html)
|
||||
print(f"📏 Размер текста: {len(regex_text):,} символов")
|
||||
print(f"📄 Первые 500 символов:")
|
||||
print("-" * 40)
|
||||
print(regex_text[:500])
|
||||
print("-" * 40)
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("🌐 МЕТОД 2: BROWSERLESS SCRAPE")
|
||||
print("="*60)
|
||||
|
||||
browserless_text = clean_with_browserless_scrape(html)
|
||||
print(f"📏 Размер текста: {len(browserless_text):,} символов")
|
||||
print(f"📄 Первые 500 символов:")
|
||||
print("-" * 40)
|
||||
print(browserless_text[:500])
|
||||
print("-" * 40)
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("📊 СРАВНЕНИЕ")
|
||||
print("="*60)
|
||||
print(f"Регулярки: {len(regex_text):,} символов")
|
||||
print(f"Browserless: {len(browserless_text):,} символов")
|
||||
print(f"Разница: {len(browserless_text) - len(regex_text):,} символов")
|
||||
|
||||
# Анализ качества
|
||||
regex_lines = regex_text.split('\n')
|
||||
browserless_lines = browserless_text.split('\n')
|
||||
|
||||
print(f"\n📈 КАЧЕСТВО:")
|
||||
print(f"Регулярки - строк: {len(regex_lines)}")
|
||||
print(f"Browserless - строк: {len(browserless_lines)}")
|
||||
|
||||
# Подсчет пустых строк
|
||||
regex_empty = sum(1 for line in regex_lines if not line.strip())
|
||||
browserless_empty = sum(1 for line in browserless_lines if not line.strip())
|
||||
|
||||
print(f"Пустые строки (регулярки): {regex_empty}")
|
||||
print(f"Пустые строки (browserless): {browserless_empty}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
compare_methods()
|
||||
Reference in New Issue
Block a user