从本地会话Telethon获取用户名

时间:2018-09-12 11:53:39

标签: python-3.x telegram telethon

我正在使用telethon库来抓取一些电报频道。抓取时,我需要解析许多加入链接,用户名和频道ID。为了解决这些问题,我使用了方法client.get_entity(),但不久后,电报服务器禁止我的搜寻器解析过多的用户名。我到处搜索并从此issue中发现,我应该使用get_input_entity()而不是get_entity()。实际上,telethon将实体保存在本地SQLite文件中,并且每当调用get_input_entity()时,它都会首先搜索本地SQLite数据库,如果找不到匹配项,则将请求发送到电报服务器。到目前为止还不错,但是这种方法存在两个问题:

  1. get_input_entity()仅返回两个属性: ID hash ,但还有其他列,例如 username phone < / em>和 name 在SQLite数据库中。我需要一种不仅返回 ID hash 的方法,而且还要返回其他列的方法。
  2. 我需要控制发送到电报服务器的解析请求的数量,但是get_input_entity()会在本地数据库中找不到匹配项时将请求发送到电报服务器。问题是,当请求电报服务器时,我无法控制此方法。实际上,我需要为该方法提供一个布尔参数,以指示当在本地数据库中找不到匹配项时,该方法是否应该向电报服务器发送请求。

我阅读了一些Telethon源代码,主要是get_input_entity(),并编写了自己的get_input_entity()版本:

def my_own_get_input_entity(self, target, with_info: bool = False):
    if self._client:
        if target in ('me', 'self'):
            return types.InputPeerSelf()
        def get_info():
            nonlocal self, result
            res_id = 0
            if isinstance(result, InputPeerChannel):
                res_id = result.channel_id
            elif isinstance(result, InputPeerChat):
                res_id = result.chat_id
            elif isinstance(result, InputPeerUser):
                res_id = result.user_id
            return self._sqlite_session._execute(
                'select username, name from entities where id = ?', res_id
            )
        try:
            result = self._client.session.get_input_entity(target)
            info = get_info() if with_info else None
            return result, info
        except ValueError:
            record_current_time()

        try:
            # when we are here, we are actually going to
            # send request to telegram servers
            if not check_if_appropriate_time_elapsed_from_last_telegram_request():
                return None
            result = self._client.get_input_entity(target)
            info = get_info() if with_info else None
            return result, info
        except ChannelPrivateError:
            pass
        except ValueError:
            pass
        except Exception:
            pass

但是我的代码在某种程度上是性能问题,因为它使对SQLite数据库的冗余查询成为可能。例如,如果target实际上是本地数据库内部的实体,而with_infoTrue,则它首先在第self._client.session.get_input_entity(target)行中查询本地数据库,并检查{{1 }}为with_info,然后再次查询数据库以获取 username name 列。在另一种情况下,如果在本地数据库中找不到True,则调用target会对本地数据库进行冗余调用。

知道了这些性能问题后,我对Telethon源代码进行了更深入的研究,但是由于我对 asyncio 的了解不多,因此我无法编写任何比上面更好的代码。

有什么想法可以解决问题吗?

0 个答案:

没有答案