如何抓取URL无变化的分页网站?以Clash of Stats为例
问题描述
我需要抓取clashofstats.com上《部落冲突》玩家档案的部落活动记录页面(示例链接:https://www.clashofstats.com/players/captain-morgan-L9YJUPY22/history/log),目标是获取玩家首次和末次游玩的近似时间。
目前已实现末次游玩时间的抓取,代码如下:
import requests from bs4 import BeautifulSoup response = requests.get('https://www.clashofstats.com/players/captain-morgan-L9YJUPY22/history/log') soup = BeautifulSoup(response.content, 'html.parser') end_dates = soup.find_all(class_="end date") last_played = str(end_dates[0]).replace("<span class=\"end date\">", "") last_played = last_played.replace(",", "") last_played = last_played.replace("</span>", "") print(f"Last time played| {last_played}")
输出结果:
Last time played| Sep 30 2022
(输出格式需匹配现有代码规范)
现在遇到的问题:部落记录分为多页,首次游玩时间在最后一页,但切换最后一页时URL和页面源码无变化,仅开发者工具中可见内容更新。想知道能否用BeautifulSoup定位最后一页并获取该日期?如果可以,该怎么实现?
解决方案
BeautifulSoup只能处理静态HTML内容,无法直接获取动态加载的页面数据——因为切换页码时的内容是通过JavaScript异步请求加载的,requests.get()拿到的只是初始页面的静态源码,不包含最后一页的内容。要获取首次游玩时间,需要换以下两种思路实现:
1. 直接调用网站API接口(推荐)
打开浏览器开发者工具的「网络」标签,切换到最后一页,观察是否有XHR/fetch请求。这类请求通常会返回JSON格式的分页数据,你可以:
- 找到返回所有活动记录的接口,直接从中提取最后一条记录的日期
- 或者先请求获取总页数的接口,再请求对应最后一页的接口数据
拿到接口后,用requests直接请求并解析JSON即可,无需处理HTML结构,效率更高。
2. 用浏览器渲染工具模拟操作
如果网站没有暴露公开API,需要用selenium或playwright模拟浏览器行为,自动加载最后一页后再提取内容。示例代码(基于selenium):
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 import time # 初始化浏览器(需提前安装对应浏览器的driver) driver = webdriver.Chrome() driver.get('https://www.clashofstats.com/players/captain-morgan-L9YJUPY22/history/log') try: # 等待分页按钮加载完成,点击最后一页按钮(需根据页面实际选择器调整) last_page_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, 'li.page-item:last-child a')) ) last_page_btn.click() # 等待页面加载完成(可根据实际情况调整等待时间) time.sleep(2) # 获取加载完成后的页面源码 page_source = driver.page_source soup = BeautifulSoup(page_source, 'html.parser') # 提取最后一页的最早日期(对应首次游玩的近似时间) end_dates = soup.find_all(class_="end date") # 用更优雅的方式提取文本,替代字符串替换标签 first_played = end_dates[-1].get_text(strip=True).replace(",", "") print(f"First time played| {first_played}") finally: # 关闭浏览器 driver.quit()
注意事项
- 需根据页面实际的分页按钮选择器调整代码中的
CSS_SELECTOR,比如如果最后一页按钮的class是last-page,就改成By.CSS_SELECTOR, '.last-page' - 若网站有反爬机制,可能需要添加请求头、代理或延长等待时间,避免被拦截
- 解析日期时优先使用
get_text()方法提取标签文本,不要直接对HTML字符串做替换操作
内容的提问来源于stack exchange,提问作者Nuspli
相关产品推荐
相关产品推荐

