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

如何用BeautifulSoup抓取NDTV孟买犯罪话题的全部文章数据?

解决NDTV话题页面全量数据抓取问题

你的代码只能获取前15篇文章,是因为NDTV采用**滚动加载(AJAX动态加载)**的方式展示更多内容,初始页面只渲染第一页数据,后续内容需要通过专门的接口请求获取。以下是修改后的代码,实现全量数据抓取:

修改思路

  1. 先抓取初始页面的第一页15条数据。
  2. 循环调用NDTV的AJAX加载接口,每次请求下一页内容,直到没有新数据返回。
  3. 解析每一次AJAX返回的HTML片段,提取文章信息并合并到结果列表中。

完整代码

import requests
from bs4 import BeautifulSoup
import csv
from datetime import datetime

def scrape_crime_data(location):
    base_url = f'https://www.ndtv.com/topic/{location}-crime'
    ajax_url = 'https://www.ndtv.com/topic/ajax-more'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
        'X-Requested-With': 'XMLHttpRequest'
    }
    crime_data = []

    # 抓取初始页面第一页数据
    response = requests.get(base_url, headers=headers)
    if response.status_code != 200:
        print(f'Error {response.status_code}: 无法获取初始页面数据')
        return []
    
    soup = BeautifulSoup(response.text, 'html.parser')
    crime_news = soup.find_all('li', class_='src_lst-li')
    if crime_news:
        for news in crime_news:
            crime_data.append(parse_news_item(news))
    
    # 循环抓取后续页面数据
    start_page = 2
    while True:
        params = {
            'topicName': f'{location}-crime',
            'startPage': start_page,
            'n': 15
        }
        ajax_response = requests.get(ajax_url, headers=headers, params=params)
        if ajax_response.status_code != 200:
            print(f'Error {ajax_response.status_code}: 无法获取第{start_page}页数据')
            break
        
        ajax_soup = BeautifulSoup(ajax_response.text, 'html.parser')
        more_news = ajax_soup.find_all('li', class_='src_lst-li')
        if not more_news:
            print(f'已获取所有数据,共{len(crime_data)}条')
            break
        
        for news in more_news:
            crime_data.append(parse_news_item(news))
        
        print(f'已获取第{start_page}页,累计{len(crime_data)}条数据')
        start_page += 1
    
    return crime_data

def parse_news_item(news):
    """提取单条新闻信息"""
    title_element = news.find('div', class_='src_itm-ttl').find('a')
    title = title_element.text.strip()
    date_text = news.find('span', class_='src_itm-stx').text.strip()
    date_start = date_text.rfind('|') + 1
    date = date_text[date_start:].strip()
    description_element = news.find('div', class_='src_itm-desc')
    description = description_element.text.strip() if description_element else ''
    return {'title': title, 'date': date, 'description': description}

# 调用示例
if __name__ == '__main__':
    mumbai_crime_data = scrape_crime_data('mumbai')
    # 保存到CSV文件
    with open('mumbai_crime_news.csv', 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=['title', 'date', 'description'])
        writer.writeheader()
        writer.writerows(mumbai_crime_data)

关键说明

  • 请求头设置:加入User-Agent和X-Requested-With模拟浏览器请求,避免被网站拦截。
  • AJAX接口参数:startPage从2开始递增,topicName对应目标话题,n控制每页返回条数(默认15)。
  • 终止条件:当AJAX返回内容中没有新闻条目时,停止循环。
  • 代码拆分:将单条新闻提取逻辑封装成独立函数,提升代码复用性和可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:55:22