Каким образом связать получаемые из телеграма сообщения и находящиеся в них изображения (Telethon)
Моя задача заключается в том, чтобы спарсить из двух телеграм каналов 10 сообщений со ссылками на содержащиеся в них изображения. Если брать изображение непосредственно из сообщения, таким образом: message.photo, то будет привязка только к первому изображению, при этом остальные изображения будут привязаны к пустым сообщениям. Пыталась связать через время следующим образом.
import json
import os
import datetime
from telethon.sync import TelegramClient
from telethon.tl.functions.messages import GetHistoryRequest
channels = ['Ozon Marketplace', 'Яндекс Маркет для продавцов']
client = TelegramClient('test', os.getenv('API_ID'), os.getenv('API_HASH'))
def main(phone):
client.start()
if not client.is_user_authorized():
client.send_code_request(phone)
client.sign_in(phone, input('Enter the code: '))
offset_id = 0
channels_data = []
all_messages = []
all_images = []
limit = 10
for channel in channels:
channel_data = client.get_entity(channel)
channels_data.append(channel_data)
history = client(GetHistoryRequest(
peer=channel_data,
offset_id=offset_id,
offset_date=None,
add_offset=0,
limit=limit,
max_id=0,
min_id=0,
hash=0
))
messages = history.messages
for i in range(len(messages)):
image_url = f'media/marketplace/{messages[i].photo.id}.png'
image_date = messages[i].photo.date
img_data = dict(model='mp_messages.image', pk=image_url, fields={'image_url': image_url,
'date': image_date})
message_data = dict(model='mp_messages.message', fields={})
if messages[i].message:
message_data['pk'] = messages[i].id
message_data['fields']['date'] = messages[i].date
message_data['fields']['message_text'] = messages[i].message
if messages[i].photo is not None:
client.download_media(messages[i].photo, image_url)
message_data['fields']['tag'] = channel
all_messages.append(message_data)
img_data['fields']['message_id'] = messages[i].message
#
for img in all_images:
if abs(messages[i].date - img['fields']['date']).seconds <= 5:
img['fields']['message_id'] = messages[i].message
else:
for message in all_messages:
if abs(message['fields']['date'] - img_data['fields']['date']).seconds <= 5:
img_data['fields']['message_id'] = message['fields']['message_text']
all_images.append(img_data)
with open('mp_messages/fixtures/channel_messages.json', 'w') as outfile:
json.dump(all_messages, outfile, ensure_ascii=False, default=str)
with open('mp_messages/fixtures/channel_images.json', 'w') as outfile:
json.dump(all_images, outfile, ensure_ascii=False, default=str)
return all_images
print(main(os.getenv('PHONE')))
Ответы (1 шт):
Проблема получения первого изображения вместо всех связана с тем, что messages[i].photo возвращает только первую фотографию в сообщении, и если в сообщении несколько фотографий, вам необходимо получить к ним доступ через messages[i].media.
Вот обновленная версия вашего кода, которая должна иметь возможность загружать все изображения в сообщении:
import json
import os
import datetime
from telethon.sync import TelegramClient
from telethon.tl.functions.messages import GetHistoryRequest
channels = ['Ozon Marketplace', 'Яндекс Маркет для продавцов']
client = TelegramClient('test', os.getenv('API_ID'), os.getenv('API_HASH'))
def main(phone):
client.start()
if not client.is_user_authorized():
client.send_code_request(phone)
client.sign_in(phone, input('Enter the code: '))
offset_id = 0
channels_data = []
all_messages = []
all_images = []
limit = 10
for channel in channels:
channel_data = client.get_entity(channel)
channels_data.append(channel_data)
history = client(GetHistoryRequest(
peer=channel_data,
offset_id=offset_id,
offset_date=None,
add_offset=0,
limit=limit,
max_id=0,
min_id=0,
hash=0
))
messages = history.messages
for i in range(len(messages)):
message_data = dict(model='mp_messages.message', fields={})
if messages[i].message:
message_data['pk'] = messages[i].id
message_data['fields']['date'] = messages[i].date
message_data['fields']['message_text'] = messages[i].message
message_data['fields']['tag'] = channel
all_messages.append(message_data)
# download all photos in message
for photo in messages[i].media.photo:
image_url = f'media/marketplace/{photo.id}.png'
image_date = photo.date
img_data = dict(model='mp_messages.image', pk=image_url, fields={'image_url': image_url,
'date': image_date,
'message_id': messages[i].id})
client.download_media(photo, image_url)
all_images.append(img_data)
else:
for message in all_messages:
for photo in messages[i].media.photo:
if abs(message['fields']['date'] - photo.date).seconds <= 5:
image_url = f'media/marketplace/{photo.id}.png'
img_data = dict(model='mp_messages.image', pk=image_url, fields={'image_url': image_url,
'date': photo.date,
'message_id': message['fields']['message_text']})
all_images.append(img_data)
with open('mp_messages/fixtures/channel_messages.json', 'w') as outfile:
json.dump(all_messages, outfile, ensure_ascii=False, default=str)
with open('mp_messages/fixtures/channel_images.json', 'w') as outfile:
json.dump(all_images, outfile, ensure_ascii=False, default=str)
return all_images
print(main(os.getenv('PHONE')))
Этот код должен быть способен загружать все изображения в сообщении, даже если в одном сообщении есть несколько фотографий. Он также включает идентификатор сообщения в данные изображения, чтобы вам было легче сопоставлять изображения с сообщениями.