爬取Telegram聊天HTML文件时如何自动补全缺失的用户名
解决方案
Telegram导出的聊天HTML本身的渲染逻辑就是:同一用户连续发送的多条消息,仅第一条会携带class="from_name"的用户名节点,后续连续消息默认继承前序消息的发送者身份,不会重复生成用户名节点,逐消息独立查找用户名必然出现空值。
修复逻辑很简单:在循环外增加一个变量缓存上一条成功解析到的用户名,当前消息找不到用户名节点时,直接复用缓存值即可。
修改后的完整代码:
messages = doc.select('div.message') rows = [] # 初始化用户名缓存变量 last_username = None for message in messages: print('---') row = {} row['id_number'] = message['id'] # 解析发送时间 try: row['time'] = message.select_one('div[title]').get('title') except AttributeError: print("Couldn't find the time") row['time'] = None # 解析用户名,找不到就复用前序缓存 try: current_username = message.select_one('div.from_name').contents[0].strip() row['username'] = current_username # 成功拿到新用户名就更新缓存 last_username = current_username except AttributeError: # 没找到用户名节点时直接用缓存值 row['username'] = last_username print("Couldn't find a name, used previous cached username") # 解析消息内容 try: row['text of the message'] = message.select_one('div.text').text.strip() except AttributeError: print("Couldn't find a text") row['text of the message'] = None print(row) rows.append(row) # 后续直接用rows生成DataFrame即可 # import pandas as pd # df = pd.DataFrame(rows)
注意点
- 不要把异常捕获写得太宽泛,原来的裸
except:会捕获所有异常(包括键盘中断、内存错误这类和解析无关的异常),改成捕获AttributeError即可,精准对应节点不存在时的报错场景。 - 缓存逻辑完全匹配Telegram导出HTML的排版规则,不会出现用户名错配问题:只要DOM里出现新的
from_name节点,就代表发送者切换,此时更新缓存就能保证后续同用户连续消息都能匹配到正确用户名。
内容的提问来源于stack exchange,提问作者user19420019
相关产品推荐
相关产品推荐

