动态滚动页面爬虫滚动失效:仅返回初始文章链接求助
问题排查与修复:SCMP贸易专题页面滚动加载爬取失效问题
问题背景
爬取SCMP贸易专题页面(https://www.scmp.com/topics/trade)的新闻文章,页面无「加载更多」按钮,文章随滚动动态生成。编写的get_article_links函数仅返回初始页面链接,滚动逻辑失效。
原代码
import time from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from bs4 import BeautifulSoup def get_article_links(url, limit_loading): options = webdriver.ChromeOptions() lists = ['disable-popup-blocking'] caps = DesiredCapabilities().CHROME caps["pageLoadStrategy"] = "normal" options.add_argument("--window-size=1920,1080") options.add_argument("--disable-extensions") options.add_argument("--disable-notifications") options.add_argument("--disable-Advertisement") options.add_argument("--disable-popup-blocking") driver = webdriver.Chrome(executable_path= r"E:\chromedriver\chromedriver.exe", options=options) #add your chrome path driver.get(url) last_height = driver.execute_script("return document.body.scrollHeight") loading = 0 while loading < limit_loading: loading += 1 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(8) new_height = driver.execute_script("return document.body.scrollHeight") if new_height == last_height: break last_height = new_height article_links = [] bsObj = BeautifulSoup(driver.page_source, 'html.parser') for i in bsObj.find('div', {'class': 'content-box'}).find('div', {'class': 'topic-article-container'}).find_all('h2', {'class': 'article__title'}): article_links.append(i.a['href']) return article_links
调用示例:
get_article_links('https://www.scmp.com/topics/trade', 5)
问题分析
- 错误的滚动容器:原代码滚动
document.body,但SCMP专题页的实际内容加载容器是div.topic__content,滚动body无法触发动态加载逻辑。 - 固定等待不可靠:
time.sleep(8)是固定时长,若网络延迟或页面加载慢,会导致新内容未加载完成就判断高度,误判为无更多内容。 - 层级定位脆弱:多层
find嵌套依赖页面结构,一旦页面微调就会定位失败,且无异常处理。
修正后的代码
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup def get_article_links(url, limit_loading): options = webdriver.ChromeOptions() options.add_argument("--window-size=1920,1080") options.add_argument("--disable-extensions") options.add_argument("--disable-notifications") options.add_argument("--disable-popup-blocking") # 初始化驱动 driver = webdriver.Chrome(executable_path=r"E:\chromedriver\chromedriver.exe", options=options) driver.get(url) wait = WebDriverWait(driver, 15) # 定位实际滚动容器 content_container = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "topic__content"))) loading = 0 last_article_count = 0 while loading < limit_loading: loading += 1 # 滚动到容器底部 driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight;", content_container) # 等待新文章加载,最多等待15秒 try: wait.until(lambda d: len(d.find_elements(By.CLASS_NAME, "article__title")) > last_article_count) last_article_count = len(driver.find_elements(By.CLASS_NAME, "article__title")) except: # 超时则认为无更多内容,退出循环 break # 额外等待1秒确保内容完全渲染 time.sleep(1) # 解析页面获取所有文章链接 article_links = [] bsObj = BeautifulSoup(driver.page_source, 'html.parser') for title_tag in bsObj.find_all('h2', {'class': 'article__title'}): if title_tag.a and 'href' in title_tag.a.attrs: article_links.append(title_tag.a['href']) driver.quit() return article_links
关键修改点
- 滚动目标修正:改为滚动页面内的
topic__content容器,触发动态加载逻辑。 - 显式等待替代固定睡眠:通过等待文章数量增加来确认新内容加载完成,比固定时长更可靠。
- 优化元素定位:直接查找所有
article__title标签,避免多层嵌套的脆弱性,增加属性判断防止空链接。 - 增加驱动关闭:添加
driver.quit()释放资源。
内容的提问来源于stack exchange,提问作者Starlord22
相关产品推荐
相关产品推荐

