[NOTE]Telegram频道图片爬虫

TG上的小姐姐频道很香啊!

Telegram频道爬虫

简介

很久之前写的TG爬虫,上面的小姐姐太好看了!

爬虫内容:实时检测频道新消息,有媒体消息就下载媒体。不是一股脑下载频道的历史媒体消息。需要长时间运行,有条件的同学丢服务器上挂着就好

另外,我写这个机器人主要想实现把TG频道的色图转到QQ群给大伙乐乐。所以这里还有一个配套的mirai插件。没有这个需求,单纯想下载媒体的可以不使用这个插件,注释掉python代码中的某一行(注释中有标注)

mirai机器人配套插件需要更新,暂时别用

需要先用pip安装好相关模块,运行一次,缺谁就安装谁

pip里面的socks似乎不顶用,archlinux用户请使用pacman安装python-socks

爬虫代码

import asyncio
import logging
import socks
import telethon.tl.types
from aiofile import AIOFile, Writer
from telethon import TelegramClient, events
from telethon.tl.types import PeerChannel

# your telegram api id
api_id = 789456123
# your telegram api hash
api_hash = 'abcdefghijklmn789456123'
# get form https://my.telegram.org/apps


# your chat id
admin_id = 123456789
# get from https://telegram.me/getidsbot

# your bot_token
bot_token = 'abcdefghijklmn123456'
# get from https://telegram.me/botfather

# file save path with writing permission
save_path = '/tmp/'
#save_path = '/home/admin/Telegram/bot_media/'

# proxy
proxy_type = socks.HTTP
proxy_addr = 'localhost'
proxy_port = 20171

# 要监视下载的频道,键名无实际作用,不要重复就行
channel = {
    "少女情怀总是诗":1336617732,
    "自己频道转发者":1167351518,
    "咸鱼的杂货铺":1445018107,
    "白丝即正义":1088679595,
    "奇闻异录与沙雕时刻":1214996122,
    "颜值即正义":1417516653,
    "快乐星球精选收集器":1109579085,
    "每日傻雕墙":1341930464
}

# 接受监视的媒体格式(tg里面直接发送gif最后是mp4格式!),如果需要下载mp4内容可以添加"image/mp4"
accept_file_format = ["image/jpeg", "image/gif", "image/png","image/webp"]

# Mirai机器人插件的地址和端口
target_addr = "localhost"
target_port = 13131

# bot登陆:留作将来开发控制程序
# bot = TelegramClient('transferBot', api_id, api_hash, proxy=(proxy_type, proxy_addr, proxy_port)).start(
#     bot_token=bot_token).start()

# 用户登陆
client = TelegramClient('transfer', api_id, api_hash, proxy=(proxy_type, proxy_addr, proxy_port)).start()

# 列表推导式 获取频道实体列表
channel_list = [PeerChannel(channel[channel_name]) for channel_name in channel]


# 过滤出监视下载的频道,如果有媒体消息就下载
@client.on(events.NewMessage(from_users=channel_list))
async def event_handler(event):
    # 获取对话
    # chat = await event.get_chat()

    # 获取message内容
    message = event.message

    # 判断是否有媒体
    if message.media is not None:
        #print("发现媒体"+message.media.stringify())
        # 下载媒体
        await download_image(message)


# 下载媒体的具体方法
async def download_image(message):
    # 获取媒体类型
    is_webpage = isinstance(message.media,telethon.tl.types.MessageMediaWebPage)
    is_photo = isinstance(message.media, telethon.tl.types.MessageMediaPhoto)
    is_doc = isinstance(message.media, telethon.tl.types.MessageMediaDocument)

    # 判断媒体是否是受支持的
    if not (is_photo or is_webpage):# 不是照片也不是网页
        if is_doc:# 如果是文件
            is_accept_media = message.media.document.mime_type in accept_file_format# 检查文件类型是否属于支持的文件类型
            if not is_accept_media:# 判断文件类型是否是需要的类型
                print("不接受的媒体类型")
                return
        # 如果不是文件就放弃(可能是音频啥的)

    # download_media()可以自动命名,下载成功后会返回文件的保存名
    filename = await client.download_media(message, save_path)
    print("媒体下载完成")
    # 下面注释的代码不知道什么原因无法在文件不存在的情况下新建文件
    # async with async_open(save_path + "1.txt", "a") as f:
    #     await f.write(filename + "\n")
    # 原消息内容输出显示
    print(message.sender.id,message.raw_text)

    # 通知mirai机器人干活(没有这个需求的可以把这句注释掉)
    await send_to_mirai(message.sender.id, message.raw_text, filename)

# 通知mirai机器人将媒体转发到QQ群
async def send_to_mirai(from_id, raw_text, filename):
    msg = str(from_id)+"\t"+filename+"\t"+raw_text+"\t"
    try:
        reader, writer = await asyncio.open_connection(target_addr, target_port)
        writer.write(msg.encode("utf-8"))
        writer.close()
        print("已通知mirai干活")
        print("-----*****-----")
    except Exception as e:
        print(e)
        print('socket通信失败!')
        await write_to_list(msg)

# 如果通知mirai失败,保存文件信息到未处理列表.txt
async def write_to_list(msg):
    async with AIOFile(save_path + "unprocessed_list.txt", "a") as list_file:
        write = Writer(list_file)
        await write(msg + "\n")
        print(msg)
        print("写入列表")
        print("-----*****-----")



async def bot_main():
    pass


# 展示登陆的信息
def show_my_inf(me):
    print("-----****************-----")
    print("Name:", me.username)
    print("ID:", me.id)
    print("-----login successful-----")


async def client_main():
    print("-client-main-")
    me = await client.get_me()
    show_my_inf(me)
    await client.run_until_disconnected()


# 日志
logging.basicConfig(format='[%(debug) 5s/%(asctime)s] %(name)s: %(message)s',
                    level=logging.WARNING)

# 主函数入口
if __name__ == '__main__':
    with client:

        # 开启异步任务
        client.loop.run_until_complete(client_main())

另外,这里提供linux的systemd单元

telethon@.service

[Unit]
Description=Telethon Channel Downloader
After=network.target

[Service]
User=admin
Restart=on-failed
WorkingDirectory=/home/admin/Telegram
ExecStart=python /home/admin/Telegram/telethonBot.py
[Install]
WantedBy=multi-user.target

将User里的admin改为自己的用户名

文件放在/etc/systemd/system/telethon.service

假如我的用户名是admin
使用sudo systemctl start telethon@admin.service开启任务
使用sudo systemctl enable telethon@admin.service开机自动开始任务
使用sudo systemctl stop telethon@admin.service结束任务

写在最后

目前,mirai插件需要我更新。有空再说

11 Comments

  • 大佬,我想知道你的apiid和apihash还有要监视的频道id是怎么获得的,我按照你留下的网址他一直返回error,期待你的答复,我邮箱1299512327@qq.com,微信zhangjingzheng6521

    • 获取api和hash的地址正常可以访问https://my.telegram.org/
      频道信息可通过转发消息到机器人@getidbot获取频道id

  • 你好,我用你的代码测试了监控我自己创建的频道可以监控到消息,但是我需要监控的那些公共频道却一个都没有监控到,我确认频道ID是正确的,请问是为什么呢,是频道可以设置不可被监控之类的吗

    • 请确认填写的是是频道id而不是群组。
      请确认是登录的是TG主体账号,Bot暂时没用

  • 可以帮我爬一下电报群成员username 吗? 我的qq 2219157932

    • 这在我的需求之外。请研究telethon的官方开发文档。它并不是很难学习

  • 在下面重新使用@events.register(events.NewMessage(pattern=’/xxx’, from_users=admin_id))之后/start指令失效,不能注册新的指令了嘛?

  • 您好,我只想要爬取频道的名称,id,简介,可是我在TELETHON的文档中并没有发现关于频道简介的信息,所以请您指点一二。yanguo0905@gmail.com这是我的邮箱,期待您的邮件回复!

    • 获取完整实体即可
      function.users.GetFullUserRequest(user_entity)
      function.channels.GetFullChannelsRequest(channel_entity)

  • 你好,我想爬取陌生人的tg群关系,有什么办法啊?

  • 请问能获取到图片的网络地址吗?不下载到本地

回复 b晴 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注