我正在使用telethon库来抓取一些电报频道。抓取时,我需要解析许多加入链接,用户名和频道ID。为了解决这些问题,我使用了方法client.get_entity()
,但不久后,电报服务器禁止我的搜寻器解析过多的用户名。我到处搜索并从此issue中发现,我应该使用get_input_entity()
而不是get_entity()
。实际上,telethon将实体保存在本地SQLite文件中,并且每当调用get_input_entity()
时,它都会首先搜索本地SQLite数据库,如果找不到匹配项,则将请求发送到电报服务器。到目前为止还不错,但是这种方法存在两个问题:
get_input_entity()
仅返回两个属性: ID 和 hash ,但还有其他列,例如 username , phone < / em>和 name 在SQLite数据库中。我需要一种不仅返回 ID 和 hash 的方法,而且还要返回其他列的方法。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_info
是True
,则它首先在第self._client.session.get_input_entity(target)
行中查询本地数据库,并检查{{1 }}为with_info
,然后再次查询数据库以获取 username 和 name 列。在另一种情况下,如果在本地数据库中找不到True
,则调用target
会对本地数据库进行冗余调用。
知道了这些性能问题后,我对Telethon源代码进行了更深入的研究,但是由于我对 asyncio 的了解不多,因此我无法编写任何比上面更好的代码。
有什么想法可以解决问题吗?