Зачем платить за новости, если их можно украсть? (Легально)
Каждое утро одно и то же: открываешь десяток вкладок, листаешь ленту, копируешь ссылки, пытаешься понять, что важно. Час времени, ноль приватности, а если использовать облачные AI-API - еще и счет прилетает приличный. Знакомо? Тогда забудьте.
Сегодня мы заставим локальную нейросеть размером в 20 миллиардов параметров делать всю черновую работу. Она будет скрейпить Instagram, гуглить, фильтровать мусор и складывать готовые дайджесты в Markdown. Без единого цента облачным провайдерам. Без отправки ваших данных на чужие серверы. Один длинный промпт - и у вас на столе свежий брифинг.
Предупреждение: этот пайплайн не для хайпожоров. Если вы ждете красивый веб-интерфейс и одну кнопку "Старт" - вам в другой блог. Тут будет код, консоль и необходимость думать головой.
Почему локальная модель? Деньги и тишина
GPT-4o - отличная модель. Но каждый запрос к ее API - это не только деньги, но и полная прозрачность. OpenAI, Google, Anthropic - все они хранят логи. Ваши промпты, ваши данные, ваши поисковые запросы. Нет, спасибо.
GPT-OSS 20B - это открытая модель, которая работает у вас на компьютере. Ей не нужен интернет после загрузки. Она не шлет ваши запросы в Кремниевую долину. А еще она бесплатная. Да, она немного тупее GPT-4 на сложных задачах. Но для структурированного сбора информации по четкому алгоритму - ее более чем достаточно. Если сомневаетесь, почитайте про то, почему LLM - не серебряная пуля. Контекст тут решает все.
Что нам понадобится? Минимум движений
- LM Studio - бесплатный десктопный клиент для запуска локальных LLM. Качаем с официального сайта.
- Модель GPT-OSS 20B в формате GGUF. Ищем на Hugging Face, скачиваем через LM Studio.
- Local Agent Framework (например, простой Python-скрипт с MCP-протоколом). Не пугайтесь аббревиатур - все проще, чем кажется.
- Python 3.10+ с библиотеками: requests, beautifulsoup4, playwright (для сложного скрейпинга).
- Терпение и 16 ГБ оперативной памяти (можно и 8, но будет медленнее).
1 Ставим и настраиваем LM Studio с моделью
Открываем LM Studio. Идем в поиск моделей. Вбиваем "GPT-OSS 20B GGUF". Выбираем версию с квантованием Q4_K_M - оптимальный баланс между качеством и размером. Скачиваем. Ждем. Пьем кофе.
После загрузки заходим в "Local Server". Выбираем скачанную модель. Важный момент - включаем опцию "Enable MCP Server". Это позволит нашему Python-скрипту общаться с моделью через сетевой протокол. Запускаем сервер. Видим в логе что-то вроде Server running at http://localhost:1234. Отлично, модель жива.
# Проверяем, что сервер отвечает
curl http://localhost:1234/v1/chat/completions -H "Content-Type: application/json" -d '{"messages":[{"role":"user","content":"Hello"}]}'
2 Пишем агента-скрейпера: не только BeautifulSoup
Самый простой способ сломать себе нервы - пытаться скрейпить современный JavaScript-сайт обычными HTTP-запросами. Не делайте так. Используйте headless-браузер. Мы возьмем Playwright - он умеет в Chrome, Firefox и WebKit.
# install playwright first: pip install playwright && playwright install
from playwright.sync_api import sync_playwright
import json
def scrape_instagram_profile(username):
"""Скрапит последние посты с Instagram профиля."""
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # без графического интерфейса
page = browser.new_page()
page.goto(f"https://www.instagram.com/{username}/")
# Ждем загрузки контента
page.wait_for_selector("article")
# Извлекаем данные - тут нужна кастомная логика под структуру сайта
posts = page.eval_on_selector_all("article a", "elements => elements.map(el => el.href)")
browser.close()
return posts[:5] # берем последние 5
Для статических сайтов хватит requests + BeautifulSoup. Но Instagram - динамический. Playwright эмулирует реальный браузер. Если нужно просто получить HTML-структуру для анализа, вспомните про Pagesource - секретное оружие для дампа сайтов.
3 Главный промпт: инструкция для нейросети-ассистента
Вот он, ключевой момент. Мы не будем просто спрашивать у модели "Что нового?". Мы дадим ей четкий алгоритм действий. Промпт - это не вопрос, это техническое задание.
Ты - автономный агент по сбору новостей. Твоя задача:
1. Получить список источников: Instagram-аккаунты @techcrunch, @wired, поисковый запрос "последние новости ИИ".
2. Для каждого источника извлечь контент за последние 24 часа.
3. Проанализировать каждый материал, выделить:
- Основную тему (1-2 слова)
- Ключевое событие или утверждение
- Упоминания компаний/персон
- Тональность (позитивная, негативная, нейтральная)
4. Отфильтровать дубликаты и малозначимые сообщения (например, рекламные посты).
5. Сгруппировать новости по темам: "Технологии", "Бизнес", "Политика".
6. Сгенерировать итоговый Markdown-файл со структурой:
## [Дата]
### [Тема]
- [Название новости]: [Краткое резюме]. Источник: [ссылка]
Ты должен выполнять шаги последовательно, сообщая о прогрессе. Не придумывай новости. Если данных нет, так и скажи.
Этот промпт отправляется в LM Studio через MCP-протокол. Модель будет его интерпретировать и управлять скриптом. Да, модель сама решает, когда вызвать функцию скрейпинга, когда сделать поиск, когда записать файл. Это не магия, а просто хорошо структурированный контекст. Если интересно, как эволюционируют такие промпты, гляньте про LoongFlow от Baidu.
4 Сшиваем все вместе: Python как клей
Теперь пишем основной скрипт, который связывает LM Studio, скрейпинг и файловую систему. Используем MCP-клиент.
import requests
import json
from scrape_functions import scrape_instagram_profile, google_search # ваши функции
LM_STUDIO_URL = "http://localhost:1234/v1/chat/completions"
class NewsAgent:
def __init__(self):
self.conversation_history = []
def send_to_llm(self, prompt):
"""Отправляет промпт в LM Studio и возвращает ответ."""
payload = {
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.1, # низкая температура для детерминированности
"max_tokens": 4000
}
response = requests.post(LM_STUDIO_URL, json=payload)
return response.json()["choices"][0]["message"]["content"]
def execute_command(self, llm_output):
"""Парсит ответ LLM, выполняет команды (скрейпинг, запись файла)."""
# Здесь логика определения, что хочет модель
if "SCRAPE_INSTAGRAM" in llm_output:
username = llm_output.split("SCRAPE_INSTAGRAM:")[1].strip()
data = scrape_instagram_profile(username)
return json.dumps(data)
elif "WRITE_FILE" in llm_output:
# ... парсим команду записи файла
pass
return "Command executed"
def run_pipeline(self, initial_prompt):
"""Основной цикл выполнения."""
current_prompt = initial_prompt
for step in range(10): # ограничим количество шагов
llm_response = self.send_to_llm(current_prompt)
print(f"Step {step}: {llm_response[:200]}...")
command_result = self.execute_command(llm_response)
# Обновляем контекст для модели
current_prompt = f"Previous output: {command_result}. Continue with next step."
agent = NewsAgent()
agent.run_pipeline(initial_prompt) # тот самый длинный промпт
Это упрощенная архитектура. В реальности нужно больше обработки ошибок и парсинга структурированных ответов модели. Но идея ясна: модель получает задачу, разбивает ее на шаги, а Python-код выполняет тяжелую работу.
Где собака зарылась: нюансы, которые всех бесят
- Скорость. GPT-OSS 20B на CPU будет думать 10-30 секунд на каждый запрос. Это не ChatGPT. Привыкайте.
- Контекстное окно. У 20B-моделей оно обычно 4K-8K токенов. Длинный промпт + история шагов могут его переполнить. Нужно четко резюмировать предыдущие шаги.
- Парсинг ответов. Модель может отвечать свободным текстом. Чтобы заставить ее выдавать структурированные команды (типа SCRAPE_INSTAGRAM:username), нужна тонкая настройка промпта. Иногда проще дать ей шаблон.
- Антибот-системы. Instagram и Google не любят скрейпинг. Playwright поможет, но если делать тысячи запросов - заблокируют. Добавляйте задержки, ротируйте User-Agent.
Самый частый баг: модель "забывает" инструкцию после нескольких шагов и начинает генерировать ерунду. Решение - периодически повторять ключевые пункты задачи в контексте. Или использовать мультиагентный подход, но только когда он действительно нужен.
Вопросы, которые вы хотели задать, но стеснялись
Это легально?
Скрапинг публичных данных для личного использования обычно легален. Но нарушать Terms of Service сайтов - нет. Не скачивайте контент массово, не обходите платные подписки. Используйте разумно.
А если сайт изменит верстку?
Сломается. Придется обновлять селекторы в скрейпинг-функциях. Автоматизировать это сложно, но можно научить модель анализировать HTML и предлагать новые селекторы. Другой уровень промпт-инжиниринга.
Почему бы не использовать готовые RSS или API новостей?
Можно. Но многие источники (особенно соцсети) не дают RSS. А платные API - это опять деньги. Наш метод - универсальный и бесплатный. Как налоговый юрист, который сделал сервис без знаний Python, мы используем то, что есть.
Можно ли подключить другие приложения, типа Spotify или Uber?
Технически да. Но нужно писать специфичные интеграции. Общая идея та же: модель получает доступ к API через ваш код. Здесь есть инструкция, но для облачных моделей. С локальной - сложнее, но приватнее.
Что дальше? Совет, который вы не ожидаете услышать
Не пытайтесь сделать этот пайплайн полностью автономным на 100%. Это ловушка. Потратите недели на обработку краевых случаев, а выхлоп будет минимальный. Локальные LLM пока не настолько надежны.
Вместо этого настройте систему так, чтобы она работала в полуавтоматическом режиме. Пусть модель собирает сырые данные, но финальный дайджест вы просматриваете сами за 5 минут. Как в автоматизации разметки датасетов - ИИ предлагает, человек подтверждает.
И последнее: храните свои промпты в безопасности. Если ваш скрипт будет работать на публичном сервере, помните про атаку Man-in-the-Prompt. Локальное - не значит неуязвимое.
Теперь идите и автоматизируйте. Только не говорите своему боссу, что вы тратите всего 10 минут в день на новости. Пусть думает, что вы работаете усердно.