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

无限滚动页面爬虫最佳实践:两种方案的优劣探讨

无限滚动网站爬取方案对比与疑问解答

我正在爬取一个带无限滚动的网站,想了解最优实现方式,目前有两种方案:

方案1:爬取-滚动循环

  • 加载页面
  • 爬取数据
  • 滚动页面
  • 爬取数据
  • 滚动页面
  • 重复上述步骤
    疑问:是否会重复爬取数据?

方案2:先滚动再全量爬取

  • 加载页面
  • 滚动页面
  • 重复滚动
  • 爬取全部数据
    疑问:是否会遗漏数据?

我已完成方案2的编码实现,想了解方案1是否可行及两种方案的优缺点。


已实现代码

滚动函数

def scroll_to_bottom(driver):
    # 用JavaScript滚动到页面底部
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)  # 根据需要调整等待时间

数据提取函数

def Site_Extract_Cal_Event(local_webdriver: webdriver, local_event_webdriver: webdriver, url_site: str, iteration: int):

    global df
    
    local_webdriver.get(url_site)
    
    logger.debug('BKRM: 提取当前页面数据')
    logger.debug('BKRM: 提取URL')

    # 多次滚动加载无限内容

    for index in range(1,iteration):
        logger.debug('BKRM: 第[' + str(index) + ']次滚动')
        scroll_to_bottom(local_webdriver)

    # 查找所有事件对应的WebElement

    xpath_event = '//*[starts-with(@id, "ep-")]' 
    div_elements = local_webdriver.find_elements("xpath",xpath_event)                                                                                                                        

    element_index = 1

    for element in div_elements: 

        element_index_text = "{:02d}".format(element_index)
        logger.debug("元素 [" + element_index_text + "] : ")

        # 查找事件时间

        xpath_time = ".//time"
        run_time = element.find_element("xpath",xpath_time) 
        logger.debug("BKRM: 时间: " + run_time.text)

        # 查找完整事件描述的URL,用于提取组织者信息

        xpath_meetup_url_link = ".//a[@class='flex h-full flex-col justify-between space-y-5 outline-offset-8 hover:no-underline']"
        run_meetup_url_link = element.find_element("xpath",xpath_meetup_url_link)
        run_meetup_url_link_text = run_meetup_url_link.get_attribute("href")
        logger.debug("BKRM: 活动链接: " + run_meetup_url_link_text)

        # 查找活动标题

        xpath_title = './/span[@class="ds-font-title-3 block break-words leading-7 utils_cardTitle__lbnC_ text-gray6"]'
        run_title = element.find_element("xpath",xpath_title)
        logger.debug("BKRM: 标题: " + run_title.text)
        
        # 查找参与人数,部分活动可能没有显示

        xpath_attendee_number = ".//span[@class='hidden sm:inline']"
        try:
            run_attendee_number = element.find_element("xpath",xpath_attendee_number)
            run_attendee_number_text_temp= run_attendee_number.text
            an_text = run_attendee_number_text_temp.split()
            run_attendee_number_text = an_text[0] 
            logger.debug("BKRM: 参与人数: " + run_attendee_number.text)

        except NoSuchElementException:
            run_attendee_number_text= "0"
            
        # 从活动详情页提取组织者名称

        run_organizer = Site_Extract_Event_Details(local_event_webdriver, run_meetup_url_link_text) 

        # run_organizer = "BKK RUNNERS"

        element_index = element_index +1

        # 创建新记录
        new_record = {'event_site':BKRM_SITE,
                    'event_date': run_time.text,
                    'event_title': run_title.text,
                    'event_organizer': run_organizer,
                    'event_attendee_number': run_attendee_number_text,
                    'event_url': run_meetup_url_link_text}

        # 将新记录追加到DataFrame
        df = df.append(new_record, ignore_index=True)
        logger.debug('添加活动: ' + run_time.text + " / " + run_title.text)

方案可行性与优缺点分析

方案1是否可行?

方案1完全可行,只要处理好重复爬取的问题即可正常运行。

针对疑问的解答

  1. 方案1是否会重复爬取数据?
    默认情况下如果每次爬取都直接抓取当前页面所有符合条件的元素,确实会重复爬取之前已经获取过的内容。但可以通过以下方式避免:
  • 记录已爬取元素的唯一标识(比如你代码中元素的id="ep-"开头的属性值),每次爬取时只处理未记录过的元素;
  • 每次滚动后只抓取新增的元素(可以通过定位滚动前最后一个元素的位置,滚动后只提取该位置之后的内容)。
  1. 方案2是否会遗漏数据?
    如果滚动次数足够、等待时间合理,一般不会遗漏数据。但存在两种可能导致遗漏的情况:
  • 滚动后页面内容加载不完整:如果time.sleep(5)的时间不足以让新内容加载完成,会导致部分元素未被渲染,爬取时就会遗漏;
  • 网站的无限滚动有加载上限:部分网站会限制滚动加载的内容数量(比如只加载前100条),这种情况下即使多次滚动也无法获取全部内容,但这属于网站本身的限制,和方案无关。

两种方案的优缺点对比

方案1:爬取-滚动循环

  • 优点:
    • 内存占用更低:不需要一次性加载所有内容到页面,适合数据量极大的场景;
    • 可以及时处理数据:爬取一部分就可以保存一部分,避免因意外中断导致全部数据丢失;
    • 容错性更强:如果某次滚动加载失败,只影响当前新增的少量数据,无需重新滚动全部内容。
  • 缺点:
    • 需要额外处理重复爬取逻辑,增加代码复杂度;
    • 整体耗时可能更长:每次爬取和滚动都有交互,步骤更多。

方案2:先滚动再全量爬取

  • 优点:
    • 逻辑简单:不需要处理重复数据,代码实现更直接;
    • 单次爬取效率高:一次性提取所有元素,减少多次交互的开销。
  • 缺点:
    • 内存占用高:页面加载大量内容后,浏览器内存占用会显著增加,可能导致卡顿甚至崩溃;
    • 风险更高:如果滚动过程中出现中断(比如网络异常、浏览器崩溃),需要重新滚动全部内容;
    • 等待时间难把控:固定的time.sleep无法适配所有加载场景,加载慢时会遗漏数据,加载快时则浪费时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:07:54