@nurl_nurl

Проблемы с работой API вк, где ошибка?

У меня есть скрипт для обработки новостей из RSS ленты. Скрипт копирует заголовок новости и пересказывает основной текст с использованием GPT-4, а затем публикует это в ВКонтакте. Однако проблема с загрузкой медиа-материалов: скрипт должен скачивать изображение с новости, загружать его на сервер ВКонтакте и прикреплять к посту, но изображение не прикрепляется.

Код
import os
import feedparser
import requests
import time
import vk_api
import g4f 

# Конфигурация
VK_ACCESS_TOKEN = "(тут мой токен вк)"
VK_GROUP_ID = -226925342  # Указание отрицательного значения сразу
RSS_FEEDS = ["http://www.playground.ru/rss/news.xml"]
KEYWORDS = [
    "шутер", "рпг", "экшен", "стратегия", "симулятор", "приключенческая игра", "платформер",
    "файтинг", "песочница", "ммо", "мморпг", "хоррор", "пазл", "инди-игры", "виртуальная реальность",
    "аркада", "квест", "спортивные игры", "гонки", "музыкальные игры", "стелс", "моба",
    "королевская битва", "playstation", "xbox", "nintendo switch", "пк", "мобильные игры",
    "вр-устройства", "пк-эксклюзивы", "консольные игры", "стриминг игр", "открытый мир", "пошаговые бои",
    "реальное время", "крафтинг", "исследование мира", "квесты", "погоня", "рейтинг", "ранговая система",
    "подземелья", "побеждение боссов", "система диалогов", "выживание", "мультиплеер", "кооператив",
    "лутбоксы", "физика", "ачивки", "трофеи", "достижения", "лидеры", "игровой процесс", "сюжет",
    "кинематографические вставки", "разработка игр", "игровой движок", "графика", "элементы сюжета",
    "игровая физика", "прокачка персонажа", "влияние выбора", "локализация", "микротранзакции",
    "платформенные элементы", "nintendo", "sony interactive entertainment", "microsoft", "ea",
    "activision blizzard", "rockstar games", "ubisoft", "bethesda softworks", "valve", "cd projekt red",
    "epic games", "square enix", "blizzard entertainment", "bioware", "insomniac games", "naughty dog",
    "fromsoftware", "the last of us", "cyberpunk 2077", "the witcher 3", "call of duty", "fortnite",
    "minecraft", "grand theft auto v", "red dead redemption 2", "assassin's creed", "overwatch", "elden ring",
    "dark souls", "apex legends", "league of legends", "valorant", "among us", "world of warcraft",
    "rocket league", "skyrim", "monster hunter world", "battlefield", "star wars", "battlefront"
]
POST_INTERVAL_MINUTES = 10
MAX_POSTS_PER_HOUR = 6
PUBLISHED_LINKS_FILE = "published_links.txt"

# Переменные для отслеживания публикаций
published_links = set()
post_count_last_hour = 0
last_post_time = time.time()

# Инициализация vk_api
vk_session = vk_api.VkApi(token=VK_ACCESS_TOKEN)
vk = vk_session.get_api()

def load_published_links():
    """Загружает опубликованные ссылки из файла."""
    if not os.path.exists(PUBLISHED_LINKS_FILE):
        return set()
    with open(PUBLISHED_LINKS_FILE, "r", encoding="utf-8") as f:
        return set(line.strip() for line in f)


def save_published_link(link):
    """Сохраняет ссылку в файл."""
    with open(PUBLISHED_LINKS_FILE, "a", encoding="utf-8") as f:
        f.write(link + "\n")


def summarize_text_g4f(text):
    """Функция для создания дружеского пересказа текста с использованием g4f."""
    try:
        prompt = f"Перескажи эту новость, словно друзьям: {text}"
        response = g4f.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}]
        )

        # Проверка, что ответ - это словарь
        print(f"Ответ от g4f: {response}")  # Отладочный вывод
        if isinstance(response, dict) and "choices" in response:
            choices = response.get("choices", [])
            if len(choices) > 0 and isinstance(choices[0], dict):
                message = choices[0].get("message", {})
                if "content" in message:
                    return message["content"].strip()
        elif isinstance(response, str):
            return response.strip()  # Если ответ не словарь, возвращаем строку

    except Exception as e:
        print(f"Ошибка при составлении пересказа: {e}")

    # Если что-то пошло не так, возвращаем первые 200 символов текста
    return text[:200]

def upload_media(image_url=None):
    """Загружает изображение на сервер ВКонтакте и возвращает его ID."""
    try:
        # Если изображение не указано, пробуем загрузить дефолтное изображение
        if not image_url:
            print("Изображение не найдено, используем дефолтное изображение.")
            image_url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQnxtNlTBvcrh2i9G7NrSK68pGvKF7IdM4rpQ&s"  # Заменить на URL дефолтного изображения

        # Получаем сервер для загрузки фотографии
        upload_server = vk.photos.getWallUploadServer(owner_id=VK_GROUP_ID)  # Минус здесь уже
        upload_url = upload_server['upload_url']
        print(f"Upload URL: {upload_url}")  # Логируем для отладки

        # Загружаем изображение по URL
        response = requests.get(image_url)
        if response.status_code != 200:
            print(f"Ошибка при скачивании изображения: {response.status_code}. Попробуем другие источники.")
            # Здесь можно добавить дополнительную логику поиска альтернативных изображений
            # Например, использование других URL из поля 'media_content' или 'enclosures'
            return None

        files = {'photo': ('image.jpg', response.content)}
        upload_response = requests.post(upload_url, files=files).json()

        # Логируем ответ от сервера загрузки
        print(f"Upload response: {upload_response}")

        if 'photo' in upload_response:
            save_response = vk.photos.saveWallPhoto(
                owner_id=VK_GROUP_ID,
                photo=upload_response['photo'],
                server=upload_response['server'],
                hash=upload_response['hash']
            )

            if save_response:
                photo_id = save_response[0]['id']
                return photo_id
            else:
                print(f"Ошибка при сохранении фотографии: {save_response}")
        else:
            print(f"Ошибка при загрузке фотографии: {upload_response}")
            return None

    except Exception as e:
        print(f"Ошибка при загрузке медиа: {e}")
        return None

def publish_to_vk(title, summary, link, attachment=""):
    """Публикует пост в ВКонтакте с заголовком, описанием, ссылкой и изображением."""
    try:
        # Логируем, что публикуем
        print(f"Публикуем пост:\nЗаголовок: {title}\nАнонс: {summary}\nСсылка: {link}\nAttachment: {attachment}")

        # Проверка, если нет media (attachment), публикуем только текст
        if not attachment:
            print(f"Публикуем пост без изображения: {title}")
        else:
            print(f"Публикуем пост с изображением: {title}")

        # Включаем более подробный лог
        response = vk.wall.post(
            owner_id=VK_GROUP_ID,  # Убедитесь, что это отрицательное значение
            from_group=1,
            message=f" {title}\n\n{summary}\nПодробнее: {link}",
            attachments=attachment,  # Добавляем параметр attachments
        )

        # Логируем ответ от ВКонтакте для диагностики
        print("Ответ от wall.post:", response)

        if "post_id" in response:
            print(f"Пост опубликован: https://vk.com/wall-{VK_GROUP_ID}_{response['post_id']}")
            return True
        else:
            # Выводим подробную ошибку для диагностики
            print(f"Ошибка при публикации на стене: {response}")
            return False
    except Exception as e:
        print(f"Ошибка при отправке запроса на публикацию: {e}")
        return False

def fetch_rss_feed(feed_url):
    """Получение и обработка RSS-ленты."""
    global published_links, post_count_last_hour, last_post_time

    print(f"Обработка RSS канала: {feed_url}")  # Отладочный вывод
    feed = feedparser.parse(feed_url)
    for entry in feed.entries:
        if entry.link in published_links:
            continue

        if any(keyword.lower() in (entry.title.lower() + entry.summary.lower()) for keyword in KEYWORDS):
            if post_count_last_hour >= MAX_POSTS_PER_HOUR:
                print("Достигнут лимит публикаций на час.")
                break

            title = entry.title
            summary = summarize_text_g4f(entry.summary)
            link = entry.link

            # Извлекаем изображение из 'enclosure' или 'media_content'
            image = None
            if 'enclosures' in entry:
                for enclosure in entry.enclosures:
                    if 'image' in enclosure.type:
                        image = enclosure.href
                        break
            elif 'media_content' in entry:
                image = entry.media_content[0]["url"]

            # Загружаем и прикрепляем изображение
            attachment = ""
            if image:
                photo_id = upload_media(image)
                if photo_id:
                    attachment = f"photo-{VK_GROUP_ID}_{photo_id}"  # Здесь изменено

            # Публикация
            if publish_to_vk(title, summary, link, attachment):
                published_links.add(entry.link)
                save_published_link(entry.link)
                post_count_last_hour += 1
                last_post_time = time.time()

                # Пауза между публикациями
                print("Публикация завершена. Ожидание 10 секунд.")  # Отладочный вывод
                time.sleep(10)  # Пауза 10 секунд

def scheduler():
    """Запускает обработку RSS лент по расписанию."""
    global post_count_last_hour
    while True:
        if time.time() - last_post_time >= 3600:
            post_count_last_hour = 0  # Сброс счетчика постов
        for feed_url in RSS_FEEDS:
            fetch_rss_feed(feed_url)
        time.sleep(600)  # Запуск проверки каждые 10 минут


# Загрузка ранее опубликованных ссылок
published_links = load_published_links()

# Запуск планировщика
scheduler()
  • Вопрос задан
  • 38 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы