Загрузить файлы в «/»

This commit is contained in:
Андрей Репин 2026-04-03 20:58:27 +00:00
commit 193099fdcc
5 changed files with 317 additions and 0 deletions

228
PythonApplication1.py Normal file
View File

@ -0,0 +1,228 @@
import os
from datetime import datetime
from collections import defaultdict
# === 10 функций ===
def load_logs(file_path: str) -> list[dict]:
"""Читает файл с логами, преобразует каждую строку в словарь"""
logs = []
try:
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
line = line.strip()
if not line:
continue
# Парсинг строки лога (формат Nginx/Common Log Format)
parts = line.split(' ')
if len(parts) < 10:
continue
ip = parts[0]
timestamp = parts[3][1:] # убираем '['
method = parts[5][1:] # убираем '"'
url = parts[6]
status = int(parts[8])
size = int(parts[9])
log_entry = {
'ip': ip,
'timestamp': timestamp,
'method': method,
'url': url,
'status': status,
'size': size
}
logs.append(log_entry)
except FileNotFoundError:
print(f"Ошибка: Файл {file_path} не найден")
return []
return logs
def filter_by_status(logs: list[dict], status_code: int) -> list[dict]:
"""Возвращает записи с заданным статус-кодом"""
return [log for log in logs if log['status'] == status_code]
def filter_by_ip_prefix(logs: list[dict], prefix: str) -> list[dict]:
"""Фильтрует записи по началу IP-адреса"""
return [log for log in logs if log['ip'].startswith(prefix)]
def get_unique_ips(logs: list[dict]) -> list[str]:
"""Возвращает отсортированный список уникальных IP-адресов"""
unique_ips = set(log['ip'] for log in logs)
return sorted(unique_ips)
def count_requests_by_method(logs: list[dict]) -> dict[str, int]:
"""Подсчитывает количество запросов по каждому HTTP-методу"""
method_count = defaultdict(int)
for log in logs:
method_count[log['method']] += 1
return dict(method_count)
def find_top_urls(logs: list[dict], n: int) -> list[tuple[str, int]]:
"""Возвращает топ-N самых часто запрашиваемых URL"""
url_count = defaultdict(int)
for log in logs:
url_count[log['url']] += 1
sorted_urls = sorted(url_count.items(), key=lambda x: x[1], reverse=True)
return sorted_urls[:n]
def get_avg_response_size(logs: list[dict]) -> float:
"""Вычисляет средний размер ответа"""
if not logs:
return 0.0
total_size = sum(log['size'] for log in logs)
return total_size / len(logs)
def filter_by_date_range(logs: list[dict], start: str, end: str) -> list[dict]:
"""Фильтрует логи по временному диапазону"""
def parse_date(date_str: str) -> datetime:
# Формат: 02/Jan/2025:13:45:12
return datetime.strptime(date_str, "%d/%b/%Y:%H:%M:%S")
start_date = parse_date(start)
end_date = parse_date(end)
filtered = []
for log in logs:
try:
log_date = parse_date(log['timestamp'])
if start_date <= log_date <= end_date:
filtered.append(log)
except:
continue
return filtered
def group_by_hour(logs: list[dict]) -> dict[int, int]:
"""Группирует количество запросов по часам суток"""
hour_count = defaultdict(int)
for log in logs:
try:
# Извлекаем час из временной метки
timestamp = log['timestamp']
# Формат: 02/Jan/2025:13:45:12
hour = int(timestamp.split(':')[0].split('/')[-1].split(':')[0])
hour_count[hour] += 1
except:
continue
return dict(hour_count)
def generate_report(logs: list[dict]) -> str:
"""Формирует текстовый отчёт"""
if not logs:
return "Нет данных для отчёта"
# Используем другие функции
method_stats = count_requests_by_method(logs)
top_urls = find_top_urls(logs, 3)
avg_size = get_avg_response_size(logs)
hourly_stats = group_by_hour(logs)
# Формируем отчёт
report = "=" * 50 + "\n"
report += "ОТЧЁТ ПО ЛОГАМ ВЕБ-СЕРВЕРА\n"
report += "=" * 50 + "\n\n"
report += "1. СТАТИСТИКА ПО HTTP-МЕТОДАМ:\n"
for method, count in sorted(method_stats.items()):
report += f" {method}: {count} запросов\n"
report += "\n2. ТОП-3 САМЫХ ЧАСТЫХ URL:\n"
for i, (url, count) in enumerate(top_urls, 1):
report += f" {i}. {url} - {count} раз(а)\n"
report += f"\n3. СРЕДНИЙ РАЗМЕР ОТВЕТА: {avg_size:.2f} байт\n"
report += "\n4. РАСПРЕДЕЛЕНИЕ ПО ЧАСАМ:\n"
for hour in sorted(hourly_stats.keys()):
report += f" {hour:02d}:00 - {hourly_stats[hour]} запросов\n"
report += "\n" + "=" * 50 + "\n"
return report
# === Функция main для демонстрации ===
def main():
# 1. Загружаем логи
logs = load_logs("data/server_logs.txt")
if not logs:
print("Не удалось загрузить логи. Проверьте наличие файла data/server_logs.txt")
return
print("=" * 60)
print("АНАЛИЗ ЛОГОВ ВЕБ-СЕРВЕРА")
print("=" * 60)
# 2. Общее количество записей
print(f"\n📊 Общее количество записей: {len(logs)}")
# 3. Уникальные IP
unique_ips = get_unique_ips(logs)
print(f"🌐 Количество уникальных IP: {len(unique_ips)}")
print(f" Примеры: {unique_ips[:3]}")
# 4. Фильтрация по статусу 404
errors_404 = filter_by_status(logs, 404)
print(f"\n❌ Количество ошибок 404: {len(errors_404)}")
# 5. Топ-2 URL с ошибками 500
errors_500 = filter_by_status(logs, 500)
top_500_urls = find_top_urls(errors_500, 2)
print(f"⚠️ Топ-2 URL с ошибками 500:")
for url, count in top_500_urls:
print(f" - {url}: {count} раз(а)")
# 6. Фильтрация по префиксу IP (пример)
local_ips = filter_by_ip_prefix(logs, "192.168.")
print(f"\n🏠 Запросы с локальных IP (192.168.*): {len(local_ips)}")
# 7. Средний размер ответа
avg_size = get_avg_response_size(logs)
print(f"📏 Средний размер ответа: {avg_size:.2f} байт")
# 8. Фильтрация по дате (пример)
date_filtered = filter_by_date_range(logs, "01/Jan/2025:00:00:00", "31/Jan/2025:23:59:59")
print(f"📅 Запросы за январь 2025: {len(date_filtered)}")
# 9. Группировка по часам
hourly = group_by_hour(logs)
peak_hour = max(hourly, key=hourly.get)
print(f"⏰ Пиковый час: {peak_hour}:00 ({hourly[peak_hour]} запросов)")
# 10. Генерация отчёта
report = generate_report(logs)
# Создаём директорию для отчётов
os.makedirs("reports", exist_ok=True)
# Сохраняем отчёт в файл
with open("reports/summary.txt", "w", encoding="utf-8") as f:
f.write(report)
print(f"\n✅ Полный отчёт сохранён в файл: reports/summary.txt")
print("\n" + "=" * 60)
# === Запуск ===
if __name__ == "__main__":
# Запускаем анализ
main()

35
PythonApplication1.pyproj Normal file
View File

@ -0,0 +1,35 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>57327018-5847-4f0c-a393-7543eefa27d5</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>PythonApplication1.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>PythonApplication1</Name>
<RootNamespace>PythonApplication1</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="PythonApplication1.py" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
the BeforeBuild and AfterBuild targets below. -->
<!--<Target Name="CoreCompile" />-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
</Project>

23
PythonApplication1.sln Normal file
View File

@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36908.2 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication1", "PythonApplication1.pyproj", "{57327018-5847-4F0C-A393-7543EEFA27D5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{57327018-5847-4F0C-A393-7543EEFA27D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57327018-5847-4F0C-A393-7543EEFA27D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6F538869-9B3B-4C48-A68A-E7622181080C}
EndGlobalSection
EndGlobal

12
server_logs.txt Normal file
View File

@ -0,0 +1,12 @@
192.168.1.10 - - [02/Jan/2025:13:45:12 +0000] "GET /index.html HTTP/1.1" 200 1024
192.168.1.11 - - [02/Jan/2025:13:46:23 +0000] "POST /api/login HTTP/1.1" 200 512
192.168.1.10 - - [02/Jan/2025:13:47:01 +0000] "GET /about.html HTTP/1.1" 404 256
10.0.0.1 - - [02/Jan/2025:14:10:34 +0000] "GET /index.html HTTP/1.1" 200 1024
192.168.1.12 - - [02/Jan/2025:14:15:45 +0000] "GET /products.html HTTP/1.1" 500 128
192.168.1.10 - - [02/Jan/2025:14:20:56 +0000] "GET /index.html HTTP/1.1" 200 1024
10.0.0.2 - - [02/Jan/2025:15:05:12 +0000] "POST /api/data HTTP/1.1" 201 2048
192.168.1.11 - - [02/Jan/2025:15:30:22 +0000] "GET /index.html HTTP/1.1" 200 1024
192.168.1.10 - - [02/Jan/2025:16:00:00 +0000] "GET /admin.html HTTP/1.1" 403 512
10.0.0.1 - - [02/Jan/2025:16:15:33 +0000] "GET /products.html HTTP/1.1" 500 128
192.168.1.13 - - [03/Jan/2025:09:00:00 +0000] "GET /index.html HTTP/1.1" 200 1024
192.168.1.10 - - [03/Jan/2025:10:30:45 +0000] "GET /api/users HTTP/1.1" 200 2048

19
summary.txt Normal file
View File

@ -0,0 +1,19 @@
==================================================
ОТЧЁТ ПО ЛОГАМ ВЕБ-СЕРВЕРА
==================================================
1. СТАТИСТИКА ПО HTTP-МЕТОДАМ:
GET: 10 запросов
POST: 2 запросов
2. ТОП-3 САМЫХ ЧАСТЫХ URL:
1. /index.html - 5 раз(а)
2. /products.html - 2 раз(а)
3. /api/login - 1 раз(а)
3. СРЕДНИЙ РАЗМЕР ОТВЕТА: 896.00 байт
4. РАСПРЕДЕЛЕНИЕ ПО ЧАСАМ:
2025:00 - 12 запросов
==================================================