从本地会话 Telethon 获取用户名
Get username from local session Telethon
我正在使用 telethon library to crawl some telegram channels. While crawling, i need to resolve many join links, usernames and channel ids. To resolve these items, i used method client.get_entity()
but after a while telegram servers banned my crawler for resolving too many usernames. I searched around and found from this issue,我应该使用 get_input_entity()
而不是 get_entity()
。实际上 telethon 将实体保存在本地 SQLite 文件中,每当调用 get_input_entity()
时,它首先搜索本地 SQLite 数据库,如果找不到匹配项,它就会向电报服务器发送请求。到目前为止一切顺利,但这种方法有两个问题:
get_input_entity()
只是 return 两个属性:ID 和 hash 但还有其他列,例如 username, phone 和 SQLite 数据库中的 name。我需要一种方法,不仅可以 return ID 和 hash,还可以 return 其他列。
- 我需要控制发送到电报服务器的解析请求的数量,但是
get_input_entity()
只要在本地数据库中找不到匹配项就会向电报服务器发送请求。问题是我无法在请求电报服务器时控制此方法。实际上,我需要此方法的布尔参数,指示当在本地数据库中找不到匹配项时,该方法是否应向电报服务器发送请求。
我阅读了一些电视节目源代码,主要是 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_info
是 True
,则它首先在 self._client.session.get_input_entity(target)
行查询本地数据库并检查是否 with_info
是 True
,然后再次查询数据库得到 username 和 name 列。在另一种情况下,如果在本地数据库中找不到 target
,则调用 self._client.get_input_entity(target)
会对本地数据库进行冗余调用。
了解这些性能问题后,我深入研究了 telethon 源代码,但由于我对 asyncio 知之甚少,我写不出比上面更好的代码。
有什么解决问题的想法吗?
client.session.get_input_entity
不会进行 API 调用(它不能),如果本地数据库中没有匹配项则失败,这可能是您想要的行为。
您现在可以访问 client.session._conn
私有属性。它是一个 sqlite3.Connection
对象,因此您可以使用它来进行所需的所有查询。请注意,由于您正在访问私有成员,因此这很容易中断,尽管预计不会很快发生变化。理想情况下,您应该将会话文件子类化以满足您的需要。请参阅文档中的 Session Files。
我正在使用 telethon library to crawl some telegram channels. While crawling, i need to resolve many join links, usernames and channel ids. To resolve these items, i used method client.get_entity()
but after a while telegram servers banned my crawler for resolving too many usernames. I searched around and found from this issue,我应该使用 get_input_entity()
而不是 get_entity()
。实际上 telethon 将实体保存在本地 SQLite 文件中,每当调用 get_input_entity()
时,它首先搜索本地 SQLite 数据库,如果找不到匹配项,它就会向电报服务器发送请求。到目前为止一切顺利,但这种方法有两个问题:
get_input_entity()
只是 return 两个属性:ID 和 hash 但还有其他列,例如 username, phone 和 SQLite 数据库中的 name。我需要一种方法,不仅可以 return ID 和 hash,还可以 return 其他列。- 我需要控制发送到电报服务器的解析请求的数量,但是
get_input_entity()
只要在本地数据库中找不到匹配项就会向电报服务器发送请求。问题是我无法在请求电报服务器时控制此方法。实际上,我需要此方法的布尔参数,指示当在本地数据库中找不到匹配项时,该方法是否应向电报服务器发送请求。
我阅读了一些电视节目源代码,主要是 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_info
是 True
,则它首先在 self._client.session.get_input_entity(target)
行查询本地数据库并检查是否 with_info
是 True
,然后再次查询数据库得到 username 和 name 列。在另一种情况下,如果在本地数据库中找不到 target
,则调用 self._client.get_input_entity(target)
会对本地数据库进行冗余调用。
了解这些性能问题后,我深入研究了 telethon 源代码,但由于我对 asyncio 知之甚少,我写不出比上面更好的代码。
有什么解决问题的想法吗?
client.session.get_input_entity
不会进行 API 调用(它不能),如果本地数据库中没有匹配项则失败,这可能是您想要的行为。
您现在可以访问 client.session._conn
私有属性。它是一个 sqlite3.Connection
对象,因此您可以使用它来进行所需的所有查询。请注意,由于您正在访问私有成员,因此这很容易中断,尽管预计不会很快发生变化。理想情况下,您应该将会话文件子类化以满足您的需要。请参阅文档中的 Session Files。