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

Scrapy增量爬取问题:仅提取NDTV网站更新的第一条头条

解决Scrapy爬取NDTV头条仅更新新内容的问题

看起来你遇到的核心问题是DeltaFetch默认的去重逻辑不匹配你的需求——它是基于请求的整体指纹(比如URL、请求头、参数等)来判断是否爬过,但NDTV的top-stories页面每次加载可能带有动态元素(比如实时时间戳、广告组件),导致每次请求的指纹都不一样,所以DeltaFetch每次都会认为是新请求,进而更新.db文件和输出的json。

下面给你几个更精准的实现方案,按推荐程度排序:

方案一:自定义本地标识去重(最简单高效)

直接放弃DeltaFetch,自己实现基于第一条头条唯一标识的去重逻辑,比如用新闻的URL作为唯一判断依据(因为每条新闻的URL是唯一且不变的)。

具体步骤:

  1. 在爬虫代码里,先提取页面第一条头条的URL;
  2. 读取本地存储的“上次爬取的第一条头条URL”;
  3. 对比两者:如果不同,就提取这条新闻的内容并保存,同时更新本地存储;如果相同,直接终止爬取。

代码示例:

import scrapy

class NDTVTopStoriesSpider(scrapy.Spider):
    name = 'test'
    start_urls = ['https://www.ndtv.com/top-stories']

    def parse(self, response):
        # 提取第一条头条的核心信息
        first_headline = response.css('.new_story h2 a')
        if not first_headline:
            self.logger.warning('No headline found on the page')
            return
        
        current_url = first_headline.attrib['href']
        current_title = first_headline.css('::text').get().strip()
        current_time = response.css('.new_story .dateline::text').get().strip()

        # 读取本地记录的上次头条URL
        saved_url = ''
        try:
            with open('last_ndtv_headline.txt', 'r') as f:
                saved_url = f.read().strip()
        except FileNotFoundError:
            # 第一次运行,文件不存在,直接处理
            pass

        if current_url != saved_url:
            # 生成Item
            yield {
                'url': current_url,
                'title': current_title,
                'publish_time': current_time
            }
            # 更新本地记录
            with open('last_ndtv_headline.txt', 'w') as f:
                f.write(current_url)
            self.logger.info('New headline found and saved!')
        else:
            self.logger.info('No update in top headline, stopping crawl.')
            return

配套设置:

  • 在settings.py里关闭DeltaFetch中间件,避免干扰:
    DOWNLOADER_MIDDLEWARES = {
        # 注释掉DeltaFetch相关的配置
        # 'scrapy_deltafetch.DeltaFetch': 100,
    }
    
  • 运行爬虫时,如果想每次只保留最新的头条,可以用覆盖模式输出:
    scrapy crawl test -o test.json --overwrite
    

方案二:修改DeltaFetch的指纹生成逻辑

如果你坚持要用DeltaFetch,可以自定义它的指纹生成规则,让指纹基于第一条头条的URL,而不是整个请求的指纹。

具体步骤:

  1. 在项目里新建一个utils.py文件,定义自定义指纹函数:
    def headline_based_fingerprint(request, spider):
        # 核心思路:用第一条头条的URL作为去重标识
        # 需要在爬虫请求的meta中传递已解析的头条URL
        if 'headline_url' in request.meta:
            return request.meta['headline_url']
        #  fallback到默认指纹
        from scrapy.utils.request import request_fingerprint
        return request_fingerprint(request)
    
  2. 在settings.py里配置DeltaFetch使用这个自定义函数:
    DELTAFETCH_FINGERPRINT_FUNC = 'your_project.utils.headline_based_fingerprint'
    DELTAFETCH_ENABLED = True
    
  3. 在爬虫的parse方法里,把第一条头条的URL放到请求的meta中(需要调整爬虫逻辑,确保请求发送前已获取到头条URL)。

这个方法相对复杂,因为DeltaFetch的设计是针对请求级别的去重,而你的需求是内容级别的,所以方案一更适配。

方案三:使用Scrapy的dupefilter自定义去重

Scrapy自带的dupefilter也可以自定义去重规则,核心思路和方案一类似,但更贴合Scrapy的架构:

  1. 自定义一个去重过滤器,基于头条URL去重;
  2. 在settings.py里配置使用这个过滤器。

不过这个实现成本比方案一高,对于你的简单需求来说,方案一已经足够。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:41:44