
本文介绍如何绕过前端按钮限制,直接从网页源码中提取 javascript 内嵌的原始数据,并使用 python 自动化生成 csv 文件,适用于 collegetennisranks 等采用 datatables + html5 buttons 的静态导出场景。
本文介绍如何绕过前端按钮限制,直接从网页源码中提取 javascript 内嵌的原始数据,并使用 python 自动化生成 csv 文件,适用于 collegetennisranks 等采用 datatables + html5 buttons 的静态导出场景。
CollegeTennisRanks(如 https://www.php.cn/link/820f0f49c5a7b094a811cd0ce3342e9e)页面上的「CSV」按钮看似提供下载入口,但实际并未发起网络请求——它由客户端 JavaScript(buttons.html5.min.js)驱动,将已加载在页面中的数据(通常以二维数组或对象形式)本地序列化为 CSV 并触发浏览器下载。因此,在 Network 面板中无法捕获任何 CSV 请求,也无法通过简单拼接 URL 获取文件。
真正的数据源隐藏在 HTML 源码中:打开页面「查看页面源代码」(Ctrl+U),可发现 标签下第一个 <script></script> 标签内,包含一段初始化 DataTables 的 JavaScript 代码,其中 data: [...] 字段即为完整的表格原始数据(常为数组的数组,如 [[ "Team A", "vs Team B", "2024-03-15" ], ...])。该数据是纯前端渲染的基础,无需额外 API 调用。
以下是一个完整、健壮的自动化方案示例(基于 requests + beautifulsoup4 + csv):
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
import requests
from bs4 import BeautifulSoup
import csv
import re
import json
def fetch_and_save_csv(url, output_path="schedules.csv"):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
# 查找 body 下第一个 script 标签(通常含 data 初始化)
script_tag = soup.body.find("script", string=re.compile(r"datas*:s*[["))
if not script_tag:
raise ValueError("未找到包含 data: [[...]] 的 script 标签,请检查页面结构是否变更")
# 提取 data 数组内容(正则匹配最外层 [ ... ])
data_match = re.search(r"datas*:s*([[.*?]])", script_tag.string, re.DOTALL)
if not data_match:
raise ValueError("未能从 script 中提取 data 数组")
try:
# 安全解析为 Python 列表(注意:此处为类 JSON 格式,非标准 JSON)
data_list = json.loads(data_match.group(1).replace("'", '"'))
except json.JSONDecodeError:
# 若含单引号或转义问题,可先做轻量清洗
cleaned = data_match.group(1).replace("'", '"').replace("\", "\\")
data_list = json.loads(cleaned)
# 写入 CSV(假设首行为表头,若无则跳过)
with open(output_path, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
# 若原始数据不含表头,可手动添加;此处按原样写入
writer.writerows(data_list)
print(f"✅ 已成功生成 {output_path},共 {len(data_list)} 行数据")
# 使用示例
if __name__ == "__main__":
fetch_and_save_csv("https://www.php.cn/link/820f0f49c5a7b094a811cd0ce3342e9e")
⚠️ 注意事项与最佳实践:
-
反爬策略:务必设置
User-Agent,部分站点会拦截默认请求头;必要时可添加time.sleep()或使用requests.Session()复用连接。 -
结构稳定性:该方法依赖页面 HTML 结构(如
body > script:first-child)和 JS 变量名(如data:)。若网站重构,需同步更新选择器或正则表达式。 -
数据清洗:内嵌数据可能含 HTML 实体(如
&)、换行符或特殊字符,建议在写入 CSV 前调用html.unescape()并对字段做str.strip()处理。 -
替代方案:若页面使用标准 JSON 初始化(如
data: JSON.parse('...')),可改用json.loads()直接解析字符串;对于更复杂场景(如动态渲染、需登录态),可考虑Playwright或Selenium启动真实浏览器执行DataTable.api().rows().data().toArray()提取。
此方法不依赖前端按钮逻辑,规避了 CORS 和请求拦截限制,真正实现“静默、稳定、可调度”的 CSV 自动化获取,是处理类似静态数据导出场景的可靠工程化路径。










