Nexia: различия между версиями
Нет описания правки |
Нет описания правки |
||
| (не показаны 2 промежуточные версии этого же участника) | |||
| Строка 12: | Строка 12: | ||
<!-- Карточка проекта --> | <!-- Карточка проекта --> | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h2 style="color: #2c3e50; border-bottom: 2px solid #48db92; padding-bottom: 10px; margin-top: 0;"> Сайт по сбору популярных статей Reddit | <h2 style="color: #2c3e50; border-bottom: 2px solid #48db92; padding-bottom: 10px; margin-top: 0;"> <b>Сайт по сбору популярных статей Reddit</b></h2> | ||
<p><b>Автор:</b> Харламова Анна</p> | <p><b>Автор:</b> Харламова Анна</p> | ||
<p><b>Группа:</b> АДЭУ-221</p> | <p><b>Группа:</b> АДЭУ-221</p> | ||
| Строка 20: | Строка 20: | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;">Введение</h3> | <h3 style="color: black;"><b>Введение</b></h3> | ||
🎯 Целью данной работы является разработка веб-приложения на основе FastAPI, предназначенного для автоматического сбора, обработки и предоставления пользователю популярных постов из Reddit и актуальных новостей с Hacker News. | 🎯 Целью данной работы является разработка веб-приложения на основе FastAPI, предназначенного для автоматического сбора, обработки и предоставления пользователю популярных постов из Reddit и актуальных новостей с Hacker News. | ||
| Строка 29: | Строка 29: | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;">Задачи проекта:</h3> | <h3 style="color: black;"><b>Задачи проекта:</b></h3> | ||
<ul> | <ul> | ||
<li>Изучить работу внешних API (Reddit и Hacker News).</li> | <li>Изучить работу внешних API (Reddit и Hacker News).</li> | ||
| Строка 43: | Строка 43: | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;">🏗 Архитектура и блок-схема проекта</h3> | <h3 style="color: black;">🏗 <b>Архитектура и блок-схема проекта</b></h3> | ||
<p>Архитектура построена по принципу клиент-серверной модели и включает несколько уровней:</p> | <p>Архитектура построена по принципу клиент-серверной модели и включает несколько уровней:</p> | ||
<div style="display: flex; flex-direction: column; align-items: center; margin-top: 20px;"> | <div style="display: flex; flex-direction: column; align-items: center; margin-top: 20px;"> | ||
<div style="position: relative; width: 360px;"> | <div style="position: relative; width: 360px;"> | ||
<div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🌐 Уровень представления (Frontend) | <div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🌐 <b>Уровень представления (Frontend)</b> | ||
<ul> | <ul> | ||
<li>Реализован через статические файлы (static)</li> | |||
<li>Отображает данные пользователю</li> | |||
<li>Отправляет HTTP-запросы к серверу</li> | |||
</ul> | |||
</div> | </div> | ||
<div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | <div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | ||
<div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🚀 Backend (API-сервер) | <div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🚀 <b>Backend (API-сервер)</b> | ||
<ul> | <ul> | ||
<li>Обработка HTTP-запросов</li> | |||
<li>Маршрутизация (/api/reddit, /api/news, /api/comments)</li> | |||
<li>Возврат данных в формате JSON</li> | |||
<li>Логирование</li> | |||
</ul> | |||
</div> | </div> | ||
<div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | <div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | ||
<div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🔌 Слой бизнес-логики | <div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🔌 <b>Слой бизнес-логики</b> | ||
<ul> | <ul> | ||
<li>RedditClient</li> | |||
<li>NewsClient</li> | |||
</ul> | |||
</div> | </div> | ||
<div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | <div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | ||
<div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🌍 Внешние API | <div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">🌍 <b>Внешние API</b> | ||
<ul> | <ul> | ||
<li>Reddit API</li> | |||
<li>Hacker News API</li> | |||
</ul> | |||
</div> | </div> | ||
<div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | <div style="width: 2px; height: 15px; background-color: #48db92; margin: 0 auto;"></div> | ||
<div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">⚙️ Инфраструктурный слой | <div style="background-color: #48db92; color: black; text-align: left; padding: 10px 0; border-radius: 8px; margin: 5px 0;">⚙️ <b>Инфраструктурный слой</b> | ||
<ul> | <ul> | ||
<li>Переменные окружения (.env)</li> | |||
<li>Логирование (logging)</li> | |||
<li>HTTP-клиент (requests)</li> | |||
<li>ASGI-сервер Uvicorn</li> | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | </div> | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;"> | <h3 style="color: black;"><b>Структура работы:</b></h3> | ||
[[Файл:Структура в среде разработки.png]] | |||
</div> | </div> | ||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | |||
<h3 style="color: black;"><b>Python-структура:</b></h3> | |||
<pre> | |||
import os | |||
import logging | |||
from fastapi import FastAPI, Query | |||
from fastapi.staticfiles import StaticFiles | |||
from dotenv import load_dotenv | |||
from reddit_client import RedditClient | |||
from news_client import NewsClient | |||
load_dotenv() | |||
log_level = os.getenv("LOG_LEVEL", "INFO") | |||
logging.basicConfig( | |||
level=log_level, | |||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", | |||
handlers=[ | |||
logging.StreamHandler(), | |||
logging.FileHandler("app.log", encoding="utf-8") | |||
] | |||
) | |||
logger = logging.getLogger(__name__) | |||
app = FastAPI(title="Nexia API") | |||
@app.on_event("startup") | |||
async def startup_event(): | |||
logger.info("Application starting up...") | |||
@app.get("/api/reddit") | |||
async def get_reddit_feed(subreddit: str = Query("popular", description="Subreddit name")): | |||
logger.info(f"API request received for /api/reddit, subreddit: {subreddit}") | |||
limit = int(os.getenv("REDDIT_LIMIT", "15")) | |||
client = RedditClient(limit=limit) | |||
result = client.fetch_posts(subreddit) | |||
if "error" in result: | |||
return {"status": "error", "message": result["error"]} | |||
return {"status": "success", "data": result["posts"]} | |||
@app.get("/api/news") | |||
async def get_news_feed(): | |||
logger.info("API request received for /api/news") | |||
client = NewsClient() | |||
news = client.fetch_latest_news(limit=15) | |||
return {"status": "success", "data": news} | |||
@app.get("/api/comments") | |||
async def get_comments(source: str = Query(..., description="Source network (e.g. reddit)"), | |||
post_id: str = Query(..., description="Post ID")): | |||
logger.info(f"API request received for /api/comments, source: {source}, id: {post_id}") | |||
if source == 'reddit': | |||
client = RedditClient() | |||
comments = client.fetch_comments(post_id) | |||
return {"status": "success", "data": comments} | |||
# News comments aren't supported in this iteration | |||
return {"status": "error", "message": "Comments not supported for this source."} | |||
app.mount("/", StaticFiles(directory="static", html=True), name="static") | |||
if __name__ == "__main__": | |||
import uvicorn | |||
logger.info("Starting uvicorn server on port 8000") | |||
uvicorn.run(app, host="0.0.0.0", port=8000) | |||
</pre> | |||
</div> | |||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;"> | <h3 style="color: black;">⚙️ <b>Логика работы приложения</b></h3> | ||
[[Файл:Логика работы приложения.png]] | |||
</div> | |||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | |||
<h3 style="color: black;"><b>Пример вывода новостей:</b></h3> | |||
[[Файл:Сайт.png]] | |||
<div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | <div style="background-color: #ffffff; padding: 20px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | ||
<h3 style="color: black;">Выводы о проделанной работе:</h3> | <h3 style="color: black;"><b>Выводы о проделанной работе:</b></h3> | ||
В ходе выполнения проекта разработано веб-приложение на FastAPI, агрегирующее данные из Reddit и Hacker News. Реализованы API-эндпоинты, обработка данных и клиент-серверная архитектура. Поставленная цель достигнута, приложение успешно выполняет сбор и предоставление актуального контента. | В ходе выполнения проекта разработано веб-приложение на FastAPI, агрегирующее данные из Reddit и Hacker News. Реализованы API-эндпоинты, обработка данных и клиент-серверная архитектура. Поставленная цель достигнута, приложение успешно выполняет сбор и предоставление актуального контента. | ||
Версия от 03:22, 27 марта 2026
| Описание | Веб-приложение, отслеживающее популярные посты с платформы Reddit. |
| Область знаний | Программирование на Python, Работа с API, Веб-технологии |
| Близкие рецепту понятия | Лента, популярное, новости |
| Среды и средства для приготовления рецепта | Python, Visual studio code |
Сайт по сбору популярных статей Reddit
Автор: Харламова Анна
Группа: АДЭУ-221
Дисциплина: Работа с API социальных сетей и визуализация данных
Статус проекта: Выполнен
Введение
🎯 Целью данной работы является разработка веб-приложения на основе FastAPI, предназначенного для автоматического сбора, обработки и предоставления пользователю популярных постов из Reddit и актуальных новостей с Hacker News. Приложение должно обеспечивать удобный доступ к агрегированному контенту через API и веб-интерфейс.
💡 Основная идея проекта — упростить доступ пользователей к актуальному и популярному контенту Reddit в удобном и структурированном виде.
Задачи проекта:
- Изучить работу внешних API (Reddit и Hacker News).
- Реализовать клиент для получения постов и комментариев с Reddit.
- Реализовать клиент для получения новостей с Hacker News.
- Создать API-эндпоинты для: получения постов, получения новостей, получения комментариев.
- Организовать обработку и структурирование данных (JSON-формат).
- Реализовать логирование работы приложения.
- Обеспечить обработку ошибок при работе с внешними сервисами.
- Подключить статические файлы для отображения пользовательского интерфейса.
🏗 Архитектура и блок-схема проекта
Архитектура построена по принципу клиент-серверной модели и включает несколько уровней:
- Реализован через статические файлы (static)
- Отображает данные пользователю
- Отправляет HTTP-запросы к серверу
- Обработка HTTP-запросов
- Маршрутизация (/api/reddit, /api/news, /api/comments)
- Возврат данных в формате JSON
- Логирование
- RedditClient
- NewsClient
- Reddit API
- Hacker News API
- Переменные окружения (.env)
- Логирование (logging)
- HTTP-клиент (requests)
- ASGI-сервер Uvicorn
Python-структура:
import os
import logging
from fastapi import FastAPI, Query
from fastapi.staticfiles import StaticFiles
from dotenv import load_dotenv
from reddit_client import RedditClient
from news_client import NewsClient
load_dotenv()
log_level = os.getenv("LOG_LEVEL", "INFO")
logging.basicConfig(
level=log_level,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler("app.log", encoding="utf-8")
]
)
logger = logging.getLogger(__name__)
app = FastAPI(title="Nexia API")
@app.on_event("startup")
async def startup_event():
logger.info("Application starting up...")
@app.get("/api/reddit")
async def get_reddit_feed(subreddit: str = Query("popular", description="Subreddit name")):
logger.info(f"API request received for /api/reddit, subreddit: {subreddit}")
limit = int(os.getenv("REDDIT_LIMIT", "15"))
client = RedditClient(limit=limit)
result = client.fetch_posts(subreddit)
if "error" in result:
return {"status": "error", "message": result["error"]}
return {"status": "success", "data": result["posts"]}
@app.get("/api/news")
async def get_news_feed():
logger.info("API request received for /api/news")
client = NewsClient()
news = client.fetch_latest_news(limit=15)
return {"status": "success", "data": news}
@app.get("/api/comments")
async def get_comments(source: str = Query(..., description="Source network (e.g. reddit)"),
post_id: str = Query(..., description="Post ID")):
logger.info(f"API request received for /api/comments, source: {source}, id: {post_id}")
if source == 'reddit':
client = RedditClient()
comments = client.fetch_comments(post_id)
return {"status": "success", "data": comments}
# News comments aren't supported in this iteration
return {"status": "error", "message": "Comments not supported for this source."}
app.mount("/", StaticFiles(directory="static", html=True), name="static")
if __name__ == "__main__":
import uvicorn
logger.info("Starting uvicorn server on port 8000")
uvicorn.run(app, host="0.0.0.0", port=8000)
Пример вывода новостей:
Выводы о проделанной работе:
В ходе выполнения проекта разработано веб-приложение на FastAPI, агрегирующее данные из Reddit и Hacker News. Реализованы API-эндпоинты, обработка данных и клиент-серверная архитектура. Поставленная цель достигнута, приложение успешно выполняет сбор и предоставление актуального контента.
1. В процессе разработки:
- Освоен фреймворк FastAPI для создания API.
- Реализовано взаимодействие с внешними REST API.
- Разработана клиент-серверная архитектура.
- Настроено логирование и обработка ошибок.
- Выполнено структурирование и преобразование данных.
2. Разработанное приложение:
- Автоматизирует получение популярных постов и новостей.
- Предоставляет единый интерфейс доступа к данным.
- Может быть масштабировано и расширено.



