You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python Discord爬虫机器人实现爬取链接去重?

问题

我正在用Python开发一个Discord机器人,给不支持邮件通知的站点做爬虫功能。不是专业学Python的,靠搜索和自学写了示例代码,之前用old_links = []列表实现去重,但机器人重启后已爬过的帖子会重复发送到Discord。现在改成把已发送的链接保存到本地old_links.txt文件,想每次定时运行时对比文件里的链接实现不重复发送,目前能把链接存到文件,但对比去重的功能没实现,求修改方案。

原代码:

async def test():
old_links = open("old_links.txt", "r", encoding="utf-8")

while True:
    base_url = 'https://www.cnbc.com/world/' async with aiohttp.ClientSession() as sess: async with sess.get(base_url, headers={'user-agent': 'Mozilla/5.0'}) as res: 
    text = await res.text() 
    soup = bs(text, 'lxml')

    title = soup.find("div", attrs={"class":"LatestNews-container"}).a.text.strip() 
    link = soup.find("div", attrs={"class":"LatestNews-container"}).a["href"]

    if link not in old_links: 
        print(f"title : {title}") 
        print(f"link : {link}") 
        f = open("old_links.txt", "w", encoding="utf-8") 
        f.write(f"{link}\n") 
        f.close()

    else: print("No update")


await asyncio.sleep(3)

解决方案

核心问题是直接把文件对象当成链接列表做判断,old_links = open("old_links.txt", "r", encoding="utf-8")得到的是文件对象,不是可迭代的链接集合,所以link not in old_links永远无法正确触发。另外原代码的写入逻辑会覆盖历史链接,每次只保留最新一条,也不符合需求。

修改步骤

  1. 读取文件为链接列表:启动或循环时,把文件内容读成列表,清理换行符和空行避免干扰判断。
  2. 安全操作文件:用with语句自动管理文件关闭,避免资源泄漏;新增链接时,把整个更新后的列表写入文件,保留所有历史记录。
  3. 修正代码缩进:原代码async with和循环内代码缩进错误,会导致语法报错,必须调整。

修改后的完整代码

import aiohttp
from bs4 import BeautifulSoup as bs
import asyncio

async def test():
    # 初始化旧链接列表,处理文件不存在的情况
    try:
        with open("old_links.txt", "r", encoding="utf-8") as f:
            # 读取所有行,过滤空行并去掉换行符
            old_links = [line.strip() for line in f if line.strip()]
    except FileNotFoundError:
        # 第一次运行文件不存在时,创建空列表
        old_links = []

    while True:
        base_url = 'https://www.cnbc.com/world/'
        async with aiohttp.ClientSession() as sess:
            async with sess.get(base_url, headers={'user-agent': 'Mozilla/5.0'}) as res:
                text = await res.text()
                soup = bs(text, 'lxml')

                # 获取最新新闻容器,增加容错判断
                news_container = soup.find("div", attrs={"class":"LatestNews-container"})
                if not news_container:
                    print("未找到新闻容器")
                    await asyncio.sleep(3)
                    continue
                
                title = news_container.a.text.strip()
                link = news_container.a["href"]

                # 判断链接是否已存在
                if link not in old_links:
                    print(f"title : {title}")
                    print(f"link : {link}")
                    # 将新链接加入列表
                    old_links.append(link)
                    # 写入完整的链接列表到文件
                    with open("old_links.txt", "w", encoding="utf-8") as f:
                        f.write("\n".join(old_links))
                else:
                    print("No update")

        await asyncio.sleep(3)

# 直接运行脚本时启动测试
if __name__ == "__main__":
    asyncio.run(test())

关键说明

  • 用try-except处理文件不存在的场景,第一次运行自动初始化空列表。
  • 读取文件时用列表推导式清理无效行,避免空行导致的误判。
  • 写入文件时用"\n".join(old_links)把整个列表转成字符串,完整保留所有历史链接。
  • 增加了新闻容器的存在判断,避免页面结构变化导致的报错。

内容的提问来源于stack exchange,提问作者Chozi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:30:23