Python 3.x 从本地会话Telethon获取用户名
我正在利用图书馆搜寻一些电报频道。在爬网时,我需要解析许多连接链接、用户名和通道ID。为了解决这些问题,我使用了方法Python 3.x 从本地会话Telethon获取用户名,python-3.x,telegram,telethon,Python 3.x,Telegram,Telethon,我正在利用图书馆搜寻一些电报频道。在爬网时,我需要解析许多连接链接、用户名和通道ID。为了解决这些问题,我使用了方法client.get_entity(),但过了一段时间,电报服务器因为解决了太多的用户名而禁止了我的爬虫程序。我四处搜索发现,我应该使用get\u input\u entity()而不是get\u entity()。实际上,telethon将实体保存在本地SQLite文件中,每当调用get\u input\u entity()时,它首先搜索本地SQLite数据库,如果没有找到匹配项
client.get_entity()
,但过了一段时间,电报服务器因为解决了太多的用户名而禁止了我的爬虫程序。我四处搜索发现,我应该使用get\u input\u entity()
而不是get\u entity()
。实际上,telethon将实体保存在本地SQLite文件中,每当调用get\u input\u entity()
时,它首先搜索本地SQLite数据库,如果没有找到匹配项,则向电报服务器发送请求。到目前为止还不错,但这种方法有两个问题:
get\u input\u entity()
只返回两个属性:ID和hash,但SQLite数据库中还有其他列,如username、phone和name。我需要一个方法,不仅返回ID和hash,还返回其他列get\u input\u entity()
,并编写了自己版本的get\u input\u entity()
:
但我的代码在某种程度上存在性能问题,因为它对SQLite数据库进行了冗余查询。例如,如果target
实际上是本地数据库中的一个实体,并且with\u info
是True
,则它首先在self.\u client.session.get\u input\u entity(target)
行中查询本地数据库,并检查with\u info
是否是True
,然后再次查询数据库以获取用户名和名称列。在另一种情况下,如果在本地数据库中找不到target
,则调用self.\u client.get\u input\u entity(target)
对本地数据库进行冗余调用
了解了这些性能问题后,我深入研究了telethon源代码,但由于我对asyncio了解不多,因此我无法编写比上述更好的代码
有没有解决问题的方法?client.session.get\u input\u entity将不进行API调用(它不能),如果本地数据库中没有匹配项,则将失败,这可能是您想要的行为 现在,您可以访问
client.session.\u conn
private属性。它是一个sqlite3.Connection
对象,因此您可以使用它来进行所有需要的查询。请注意,这很容易中断,因为您正在访问一个私有成员,尽管预计不久不会有任何更改。理想情况下,您应该对会话文件进行子类化,以满足您的需要。请参阅文档中的
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