BeautifulSoup与Selenium均无法抓取odb.org动态网页内容该如何解决
问题原因分析
- BeautifulSoup方案失效原因:目标站点内容由前端JS动态渲染,且默认
requests请求缺少符合浏览器规范的请求头,触发反爬策略,返回的是未加载内容的初始HTML骨架。 - Selenium方案失效原因:你的代码存在三处核心错误:
driver.get(url)方法无返回值,打印content必然是空值,正确操作是调用driver.page_source获取渲染后的页面源码- 未添加页面加载等待逻辑,页面资源还未渲染完成就读取源码,拿到的自然是未加载内容的初始结构
- 代码拼写错误:类名是
webdriver.Chrome而非Chrom
可行解决方案
方案1:修正后的Selenium实现
添加显式等待,获取渲染完成后的页面源码,再配合BeautifulSoup解析即可,代码示例:
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 import datetime as d from bs4 import BeautifulSoup as bs # 配置Chrome参数,规避反爬检测 chrome_options = Options() # 无头模式可根据需要开启/关闭 # chrome_options.add_argument("--headless=new") chrome_options.add_argument("--disable-blink-features=AutomationControlled") chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option("useAutomationExtension", False) PATH = "你的chromedriver本地路径" driver = webdriver.Chrome(executable_path=PATH, options=chrome_options) # 移除webdriver特征,避免被反爬识别 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})" }) # 构造日期路径 full_date = d.date.today() format_date = full_date.strftime("%Y/%m/%d") url = f"https://odb.org/TW/{format_date}" driver.get(url) # 显式等待目标内容加载完成,可根据实际页面结构调整选择器 try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".page-content")) ) # 获取渲染后的完整源码 page_source = driver.page_source soup = bs(page_source, 'lxml') print(soup) finally: driver.quit()
方案2:直接调用站点公开API(更高效)
目标站点的内容是通过后端API返回的,无需模拟浏览器渲染,直接请求对应接口即可拿到结构化的JSON内容,性能远高于Selenium方案:
import requests import datetime as d full_date = d.date.today() format_date = full_date.strftime("%Y/%m/%d") # 台湾地区内容接口 api_url = f"https://api.odb.org/v3/pages/TW/{format_date}" 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", "Accept": "application/json" } res = requests.get(api_url, headers=headers) content = res.json() print(content) # 正文、标题、音频等内容都可以直接从JSON字段中提取,无需解析HTML
注意事项
- 站点有请求频率限制,短时间内多次请求可能会被临时封禁IP,建议添加请求间隔
- 若需要长期抓取,建议定期更新请求头的User-Agent值,降低被反爬识别的概率
内容的提问来源于stack exchange,提问作者Ethan Wu
相关产品推荐
相关产品推荐

