如何用BeautifulSoup抓取NDTV孟买犯罪话题的全部文章数据?
解决NDTV话题页面全量数据抓取问题
你的代码只能获取前15篇文章,是因为NDTV采用**滚动加载(AJAX动态加载)**的方式展示更多内容,初始页面只渲染第一页数据,后续内容需要通过专门的接口请求获取。以下是修改后的代码,实现全量数据抓取:
修改思路
- 先抓取初始页面的第一页15条数据。
- 循环调用NDTV的AJAX加载接口,每次请求下一页内容,直到没有新数据返回。
- 解析每一次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
相关产品推荐
相关产品推荐

