Проект аудита отелей: основные скрипты и документация
- Краулеры: smart_crawler.py, regional_crawler.py - Аудит: audit_orel_to_excel.py, audit_chukotka_to_excel.py - РКН проверка: check_rkn_registry.py, recheck_unclear_rkn.py - Отчёты: create_orel_horizontal_report.py - Обработка: process_all_hotels_embeddings.py - Документация: README.md, DB_SCHEMA_REFERENCE.md
This commit is contained in:
149
export_website_status_report.py
Normal file
149
export_website_status_report.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Экспорт отчета о доступности сайтов в Excel
|
||||
"""
|
||||
|
||||
import psycopg2
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from urllib.parse import unquote
|
||||
from datetime import datetime
|
||||
import pandas as pd
|
||||
|
||||
# Конфигурация БД
|
||||
DB_CONFIG = {
|
||||
'host': "147.45.189.234",
|
||||
'port': 5432,
|
||||
'database': "default_db",
|
||||
'user': "gen_user",
|
||||
'password': unquote("2~~9_%5EkVsU%3F2%5CS")
|
||||
}
|
||||
|
||||
def export_website_status_report(region_name=None, output_file=None):
|
||||
"""Экспорт отчета в Excel"""
|
||||
|
||||
conn = psycopg2.connect(**DB_CONFIG, cursor_factory=RealDictCursor)
|
||||
cur = conn.cursor()
|
||||
|
||||
# Формируем запрос
|
||||
where_clause = ""
|
||||
params = []
|
||||
if region_name:
|
||||
where_clause = "WHERE region_name ILIKE %s"
|
||||
params = [f'%{region_name}%']
|
||||
|
||||
# Получаем данные
|
||||
query = f'''
|
||||
SELECT
|
||||
region_name as "Регион",
|
||||
full_name as "Название отеля",
|
||||
website_address as "Адрес сайта",
|
||||
CASE website_status
|
||||
WHEN 'accessible' THEN '✅ Доступен'
|
||||
WHEN 'no_website' THEN '❌ Отсутствует'
|
||||
WHEN 'timeout' THEN '⏱️ Таймаут'
|
||||
WHEN 'connection_refused' THEN '🚫 Соединение отклонено'
|
||||
WHEN 'dns_error' THEN '🔍 DNS ошибка'
|
||||
WHEN 'ssl_error' THEN '🔒 SSL ошибка'
|
||||
WHEN 'http_error' THEN '⚠️ HTTP ошибка'
|
||||
WHEN 'invalid_url' THEN '❓ Неверный URL'
|
||||
ELSE '⏳ Не проверено'
|
||||
END as "Статус сайта",
|
||||
CASE
|
||||
WHEN website_status = 'accessible' THEN 'Да'
|
||||
WHEN website_status = 'no_website' THEN 'Нет'
|
||||
ELSE 'Есть, но недоступен'
|
||||
END as "Наличие сайта",
|
||||
phone as "Телефон",
|
||||
email as "Email",
|
||||
owner_full_name as "Владелец",
|
||||
owner_inn as "ИНН"
|
||||
FROM hotel_main
|
||||
{where_clause}
|
||||
ORDER BY region_name, website_status, full_name
|
||||
'''
|
||||
|
||||
cur.execute(query, params)
|
||||
data = cur.fetchall()
|
||||
|
||||
# Создаем DataFrame
|
||||
df = pd.DataFrame(data)
|
||||
|
||||
# Получаем статистику
|
||||
stats_query = f'''
|
||||
SELECT
|
||||
region_name as "Регион",
|
||||
COUNT(*) as "Всего отелей",
|
||||
COUNT(CASE WHEN website_address IS NOT NULL AND website_address != '' AND website_address != '-' THEN 1 END) as "С указанным сайтом",
|
||||
COUNT(CASE WHEN website_status = 'accessible' THEN 1 END) as "Сайт доступен",
|
||||
COUNT(CASE WHEN website_status IN ('timeout', 'connection_refused', 'dns_error', 'ssl_error', 'http_error', 'invalid_url') THEN 1 END) as "Сайт недоступен",
|
||||
COUNT(CASE WHEN website_status = 'no_website' THEN 1 END) as "Сайт отсутствует",
|
||||
ROUND(COUNT(CASE WHEN website_status = 'accessible' THEN 1 END) * 100.0 / NULLIF(COUNT(CASE WHEN website_address IS NOT NULL AND website_address != '' AND website_address != '-' THEN 1 END), 0), 2) as "% доступности"
|
||||
FROM hotel_main
|
||||
{where_clause}
|
||||
GROUP BY region_name
|
||||
ORDER BY region_name
|
||||
'''
|
||||
|
||||
cur.execute(stats_query, params)
|
||||
stats_data = cur.fetchall()
|
||||
stats_df = pd.DataFrame(stats_data)
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# Формируем имя файла
|
||||
if not output_file:
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
region_suffix = f"_{region_name.replace(' ', '_')}" if region_name else "_все_регионы"
|
||||
output_file = f"website_status_report{region_suffix}_{timestamp}.xlsx"
|
||||
|
||||
# Сохраняем в Excel
|
||||
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
|
||||
# Лист со статистикой
|
||||
stats_df.to_excel(writer, sheet_name='Статистика', index=False)
|
||||
|
||||
# Лист с детальными данными
|
||||
df.to_excel(writer, sheet_name='Детальные данные', index=False)
|
||||
|
||||
# Лист с проблемными сайтами
|
||||
problematic_df = df[df['Наличие сайта'] == 'Есть, но недоступен'].copy()
|
||||
problematic_df.to_excel(writer, sheet_name='Недоступные сайты', index=False)
|
||||
|
||||
# Автоматическая ширина колонок
|
||||
for sheet_name in writer.sheets:
|
||||
worksheet = writer.sheets[sheet_name]
|
||||
for column in worksheet.columns:
|
||||
max_length = 0
|
||||
column_letter = column[0].column_letter
|
||||
for cell in column:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except:
|
||||
pass
|
||||
adjusted_width = min(max_length + 2, 50)
|
||||
worksheet.column_dimensions[column_letter].width = adjusted_width
|
||||
|
||||
print(f"✅ Отчет сохранен: {output_file}")
|
||||
print(f"📊 Всего записей: {len(df)}")
|
||||
print(f"🔴 Недоступных сайтов: {len(problematic_df)}")
|
||||
|
||||
return output_file
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
region = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
output = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
|
||||
if region:
|
||||
print(f"📍 Генерация отчета для региона: {region}")
|
||||
else:
|
||||
print("📍 Генерация отчета для всех регионов")
|
||||
|
||||
export_website_status_report(region, output)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user