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

使用Beautiful Soup无法从Angular站点NPTEL抓取课程列表

解决NPTEL课程页面爬取不到app-course-card标签的问题

问题根源分析

  • Requests+BeautifulSoup失效原因:NPTEL课程页面基于Angular框架构建,初始请求返回的HTML仅包含框架占位符,app-course-card标签是JavaScript动态渲染生成的,不会出现在静态HTML源码中。
  • Selenium代码的疏漏:
    1. 仅使用implicitly_wait不足以确保元素完全渲染:隐式等待是针对元素查找操作的超时等待,而你直接在页面加载后立即获取page_source,此时Angular可能还未完成课程卡片的渲染。
    2. 未针对目标元素做显式等待:没有等待app-course-card元素实际出现在DOM中。
    3. Headless模式可能导致页面渲染异常:无界面模式下默认窗口尺寸过小,部分页面内容可能不会触发加载。
    4. 最终代码未尝试提取app-course-card标签:你的Selenium代码仅返回了页面全部文本,根本没有执行查找目标标签的逻辑。

修正后的Selenium方案

使用显式等待确保目标元素加载完成,同时优化Headless模式配置:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup

chrome_options = Options()
chrome_options.add_argument('--headless=new')  # 使用新版Headless模式,兼容性更好
chrome_options.add_argument('--window-size=1920,1080')  # 设置窗口尺寸,避免内容不加载
chrome_options.add_argument('--disable-gpu')  # 禁用GPU加速,避免Headless模式异常

driver = webdriver.Chrome(options=chrome_options)

def extract_nptel_courses(url):
    driver.get(url)
    # 显式等待,直到至少一个app-course-card元素出现,超时20秒
    try:
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.TAG_NAME, 'app-course-card'))
        )
    except Exception as e:
        print(f"等待课程卡片加载失败: {e}")
        return None
    
    # 获取渲染完成的页面源码
    page_source = driver.page_source
    soup = BeautifulSoup(page_source, 'html.parser')
    
    # 提取所有课程卡片内容
    courses = []
    for card in soup.select('app-course-card'):
        # 根据实际DOM结构提取课程名称(可自行扩展提取链接、简介等)
        course_name = card.find('h3').get_text(strip=True) if card.find('h3') else "未知课程"
        courses.append(course_name)
    
    return courses

url = "https://nptel.ac.in/courses"
course_list = extract_nptel_courses(url)

if course_list:
    print("获取到的课程列表:")
    for idx, course in enumerate(course_list, 1):
        print(f"{idx}. {course}")

driver.quit()

更高效的替代方案:直接调用API

Angular页面通常通过API获取数据,你可以通过浏览器开发者工具的「网络」面板,筛选XHR/Fetch请求,找到返回课程列表的API接口。直接请求API可以避免Selenium的性能开销,示例代码:

import requests

def get_courses_via_api():
    # 替换为实际找到的API地址(需通过浏览器开发者工具确认)
    api_url = "https://nptel.ac.in/api/courses/list"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
    }
    response = requests.get(api_url, headers=headers)
    if response.status_code == 200:
        data = response.json()
        # 根据API返回的JSON结构提取课程信息
        courses = [item['courseName'] for item in data.get('courses', [])]
        return courses
    else:
        print(f"API请求失败,状态码:{response.status_code}")
        return None

course_list = get_courses_via_api()
if course_list:
    print("API获取的课程列表:")
    for course in course_list:
        print(course)

注意:API接口可能会有变化,需要自行通过浏览器开发者工具确认最新的接口地址和请求参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:25:22