Задать вопрос
@lic3mer

Как vk_боту с помощью Python скачать изображение?

Есть программа на Python. Она должна считывать новые входящие сообщения в сообщество от указанного человека. Если сообщение содержит "ключ", то сохранять на устройство текст сообщения и фото, если оно имеется.
Если сообщение не содержит вложений, то текст сохраняется, но если добавляю фотографию, то программа не может обнаружить его в item и отсылает в консоль 1.
В чем проблема?

Вот код:

import vk_api
from vk_api.longpoll import VkLongPoll, VkEventType
import requests
import os
import time

group_token = 'токен сообщества'
vk_session = vk_api.VkApi(token=group_token)
vk = vk_session.get_api()

current_dir = os.path.dirname(os.path.abspath(__file__))
id_path = os.path.join(current_dir, 'id.dat')

with open(id_path, 'r') as f:
    target_user_id = f.read().strip()

def download_file(url, path):
    response = requests.get(url)
    with open(path, "wb") as f:
        f.write(response.content)

def get_photo_link(photo):
     for size in photo['sizes']:
         if size['type'] == 'm':
             return size['url']
            
def download_photo(photo, path):
     url = get_photo_link(photo)
     filename = os.path.basename(path)
     current_dir = os.path.dirname(path)
     extension = os.path.splitext(filename)[1]
     photo_path = os.path.join(current_dir, f'file{extension}')
     download_file(url, photo_path)

filename = 'messages.txt'
path = os.path.join(os.getcwd(), filename)
longpoll = VkLongPoll(vk_session)

for event in longpoll.listen():
    if event.type == VkEventType.MESSAGE_NEW and event.from_user and str(event.user_id) == target_user_id:
        if 'ключевое_слово' in event.text:
            attachments = vk.messages.getHistoryAttachments(peer_id=event.peer_id, media_type='photo', count=1)['items']
            if attachments:
                item = attachments[0]
                if 'photo' in item:
                    text = item['photo'].get('text', '')
                    print (text)
                    extension = '.jpg'
                    photo_path = os.path.join(os.getcwd(), f'photo{extension}')
                    download_photo(item['photo'], photo_path)
                    vk.messages.send(peer_id=event.peer_id, random_id=0, message='Фото успешно загружено и текст сохранен в файле messages.txt')
                else:
                    print ('1')
                    pass
            else:
                with open(path, 'w', encoding='utf-8') as file:
                    file.write(f'{event.text}\n')
                vk.messages.send(peer_id=event.peer_id, random_id=0, message='Не удалось загрузить фото, потому что оно не было обнаружено, но текст сообщения сохранен в файле messages.txt')
  • Вопрос задан
  • 249 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 2
mayton2019
@mayton2019
Bigdata Engineer
Почему вы Питонисты никогда не обрабатываете коды ошибок http?
def download_file(url, path):
    response = requests.get(url)
    with open(path, "wb") as f:
        f.write(response.content)


request.get - возвращает статус. Это может быть 300-тка. Ошибка клиента. 400-тка. Секюрити. Или 500-тка
баги на сервере. Вот что у тебя пришло?
Ответ написан
@lic3mer Автор вопроса
В общем решением этой проблемы послужило использование метода vk.messages.getById, вместо vk.messages.getHistoryAttachments.

Конечный рабочий код:
import vk_api
from vk_api.longpoll import VkLongPoll, VkEventType
import requests
import os
import time

group_token = 'токен сообщества'
vk_session = vk_api.VkApi(token=group_token)
vk = vk_session.get_api()

current_dir = os.path.dirname(os.path.abspath(__file__))
id_path = os.path.join(current_dir, 'id.dat')

with open(id_path, 'r') as f:
    target_user_id = f.read().strip()

def download_file(url, path):
    response = requests.get(url)
    with open(path, "wb") as f:
        f.write(response.content)

def get_photo_link(photo):
     for size in photo['sizes']:
         if size['type'] == 'm':
             return size['url']
            
def download_photo(photo, path):
     url = get_photo_link(photo)
     filename = os.path.basename(path)
     current_dir = os.path.dirname(path)
     extension = os.path.splitext(filename)[1]
     photo_path = os.path.join(current_dir, f'file{extension}')
     download_file(url, photo_path)

filename = 'messages.txt'
path = os.path.join(os.getcwd(), filename)
longpoll = VkLongPoll(vk_session)

for event in longpoll.listen():
    if event.type == VkEventType.MESSAGE_NEW and event.from_user and str(event.user_id) == target_user_id:
        if 'ключевое_слово' in event.text:
            attachments = vk.messages.getById(message_ids=event.message_id, extended=True, fields='attachments')['items'][0]['attachments']
            if attachments:
                attachment = attachments[0]
                if attachment['type'] == 'photo':
                    photo = attachment['photo']
                    text = photo.get('text', '')
                    download_photo(photo, 'photo.jpg')
                    with open('messages.txt', 'a', encoding='utf-8') as file:
                        file.write(f'{text}\n')
                    vk.messages.send(peer_id=event.peer_id, random_id=0, message='Фото успешно загружено и текст сохранен в файле messages.txt')
                else:
                    vk.messages.send(peer_id=event.peer_id, random_id=0, message='Найдено вложение другого типа')
            else:
                with open('messages.txt', 'w', encoding='utf-8') as file:
                    file.write(f'{event.text}\n')
                vk.messages.send(peer_id=event.peer_id, random_id=0, message='Вложений не обнаружено, но текст сообщения сохранен в файле messages.txt')
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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