Python+AI轻松抓取百度网盘多级文件目录
前言
在现代软件开发中,AI辅助编程已经成为提升开发效率的重要工具。本文将分享一个真实案例:如何利用AI快速完成网页数据抓取任务——百度网盘多级目录树的抓取实践。本文会揭秘python+ai网抓的全流程代码
传统开发 vs AI辅助开发
传统开发流程的痛点
在没有AI辅助的情况下,完成一个网页数据抓取项目通常需要:
-
1. 分析页面结构:手动查看HTML源码,定位目标元素 -
2. 编写选择器:反复测试CSS Selector或XPath表达式 -
3. 处理异步加载:分析网络请求,找出数据接口 -
4. 调试代码:不断修改代码,处理各种边界情况 -
5. 重构优化:整理代码结构,提高可维护性
这个过程往往需要数小时甚至数天时间,尤其是面对复杂的单页应用(SPA)时。
本次实现 基本全部用AI实现 手写参与修改代码不到5行
AI编程带来的革命性改变
使用AI辅助编程,整个流程可以简化为:
-
1. 投喂页面数据:将HTML源码直接给AI -
2. 描述需求:用自然语言说明要提取什么数据 -
3. 获得代码:AI自动生成提取逻辑(JavaScript) -
4. 转换实现:AI将JS代码转为Python Playwright实现
效率提升:从数小时到几十分钟!
本文对应的直播视频回放 在郑广学python办公自动化课程里已更新
百度网盘多级目录树抓取
项目需求
抓取百度网盘分享链接中的完整目录结构,包括:
-
· 多级文件夹嵌套 -
· 文件名、大小、修改时间 -
· 导出为JSON格式 -
· 以树状结构打印
核心实现思路
1. 文件列表提取
使用Playwright定位页面元素,提取文件信息:
def extract_file_list(page) -> List[Dict[str, str]]:
"""从当前页面提取文件列表信息"""
page.wait_for_selector("dd.g-clearfix.AuPKyz", timeout=10000)
file_items = page.query_selector_all("dd.g-clearfix.AuPKyz")
result = []
for item in file_items:
# 提取文件名
filename_elem = item.query_selector("a.filename")
filename = filename_elem.get_attribute("title") if filename_elem else "未知文件"
# 提取大小和时间
size_elem = item.query_selector(".file-size")
time_elem = item.query_selector(".ctime")
size = size_elem.text_content().strip() if size_elem else ""
time = time_elem.text_content().strip() if time_elem else ""
# 判断文件类型
icon_elem = item.query_selector(".JS-fileicon")
icon_class = icon_elem.get_attribute("class") if icon_elem else ""
file_type = "folder" if "dir-small" in icon_class else "file"
result.append({
"filename": filename,
"size": size,
"time": time,
"file_type": file_type
})
return result
AI编程技巧:
-
· 这里的选择器 "dd.g-clearfix.AuPKyz"是通过AI分析百度网盘页面HTML得到的 -
· 只需要告诉AI:”百度网盘文件列表是如何渲染的”,AI会自动找出最优选择器
2. 递归遍历目录
核心算法:递归构建目录树
def build_directory_tree(page, base_url: str, current_path: str = "/",
parent_path: str = "") -> List[Dict]:
"""递归构建目录树"""
print(f"🔍 正在处理目录: {current_path}")
# 构造新URL(URL编码)
new_url = f"{base_url}#list/path={requote(current_path)}&parentPath=%2F"
page.goto(new_url)
# 获取当前目录下的所有项
items = extract_file_list(page)
result = []
for item in items:
# 构建完整路径
full_path = (parent_path + item["filename"]).rstrip("/")
if item["file_type"] == "folder":
full_path += "/"
item_with_path = item.copy()
item_with_path["full_path"] = full_path
result.append(item_with_path)
# 如果是文件夹,递归进入
if item["file_type"] == "folder":
sub_items = build_directory_tree(
page, base_url,
current_path + item["filename"] + "/",
full_path
)
result.extend(sub_items)
return result
设计亮点:
-
· 通过修改URL的 path参数实现目录切换 -
· 递归深度优先遍历所有子目录 -
· 记录完整路径,便于后续数据处理
3. 数据结构转换
将平铺的列表转换为嵌套字典:
def convert_tree_to_dict(tree: List[Dict]) -> Dict:
"""将目录树列表转换为多级字典形式"""
root = {}
for item in tree:
path_parts = [p for p in item["full_path"].split("/") if p]
current_level = root
# 遍历路径的每一级
for i, part in enumerate(path_parts):
if i == len(path_parts) - 1: # 最后一级
if item["file_type"] == "folder":
if part not in current_level:
current_level[part] = {}
else:
current_level[part] = {
"type": "file",
"size": item["size"],
"time": item["time"]
}
else: # 中间路径
if part not in current_level:
current_level[part] = {}
current_level = current_level[part]
return root
4. 可视化输出
树状结构打印:
def print_directory_tree(dictionary: Dict, indent: int = 0) -> None:
"""以多层目录树样式打印"""
for key, value in dictionary.items():
# 判断是文件夹还是文件
is_folder = isinstance(value, dict) and not all(
k in ["type", "size", "time"] for k in value.keys()
)
icon = "📁" if is_folder else "📄"
print(" " * indent + icon + " " + key)

# 递归打印子目录
if is_folder:
print_directory_tree(value, indent + 1)
主程序整合
def 抓取百度网盘文件目录树(share_url):
"""爬取百度网盘目录树的主函数"""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto(share_url)
# 获取基础URL
base_url = share_url.split('#')[0]
# 开始递归构建目录树
tree = build_directory_tree(page, base_url)
# 转换为字典形式
tree_dict = convert_tree_to_dict(tree)
# 打印树状结构
print("n🌳 多级字典形式的目录树:")
print_directory_tree(tree_dict)
# 保存为JSON文件
with open("directory_tree.json", "w", encoding="utf-8") as f:
json.dump(tree_dict, f, ensure_ascii=False, indent=2)
print("n✅ 目录树已保存到 directory_tree.json")
browser.close()
return tree_dict
if __name__ == "__main__":
share_url = "https://pan.baidu.com/s/1H_iu_2sPcvRMdPyXnxXs3w?pwd=e7vv"
抓取百度网盘文件目录树(share_url)
AI编程的最佳实践
1. 精准的需求描述
❌ 不好的提问:
帮我写一个爬虫
✅ 好的提问:
使用Python Playwright抓取百度网盘分享链接的文件列表,需要:
1. 递归遍历所有子文件夹
2. 提取文件名、大小、修改时间
3. 输出为JSON格式
4. 处理中文文件名的URL编码
2. 分步骤实现
将复杂任务拆解:
-
1. 第一步:只提取单层目录 -
2. 第二步:添加递归逻辑 -
3. 第三步:优化数据结构 -
4. 第四步:添加可视化功能
每一步都让AI生成代码,逐步验证。
3. 提供上下文
给AI提供足够的信息:
我已经有了提取单层目录的代码(附上代码),现在需要递归遍历子文件夹。
百度网盘通过修改URL的hash参数来切换目录,格式为:
#list/path=/文件夹名/&parentPath=%2F
请帮我实现递归遍历逻辑。
4. 迭代优化
第一版代码可能不完美,继续向AI提问:
这段代码有以下问题:
1. 中文路径没有正确编码
2. 空文件夹判断逻辑有误
3. 递归深度可能过大导致栈溢出
请帮我优化
关键技术点总结
1. Playwright选择器策略
# 等待元素加载
page.wait_for_selector("dd.g-clearfix.AuPKyz", timeout=10000)
# 批量查询
items = page.query_selector_all("dd.g-clearfix.AuPKyz")
# 属性提取
title = elem.get_attribute("title")
text = elem.text_content().strip()
2. URL参数处理
from urllib.parse import quote, unquote
def requote(path: str) -> str:
"""对路径进行URL编码"""
return quote(path, safe='/') # / 不编码
3. 递归算法设计
def recursive_crawl(current_path):
items = get_items(current_path)
for item in items:
if is_folder(item):
# 递归调用
recursive_crawl(current_path + item.name)
4. 数据结构优化
# 列表形式(易于遍历)
tree_list = [
{"full_path": "/folder1/file1.txt", "size": "1MB"},
{"full_path": "/folder1/file2.txt", "size": "2MB"}
]
# 字典形式(易于查询和展示)
tree_dict = {
"folder1": {
"file1.txt": {"type": "file", "size": "1MB"},
"file2.txt": {"type": "file", "size": "2MB"}
}
}
常见问题与解决方案
问题1:选择器失效
原因:页面结构动态变化,元素延迟加载
解决:
# 使用wait_for_selector确保元素加载完成
page.wait_for_selector("目标选择器", timeout=10000)
# 或者等待网络空闲
page.wait_for_load_state("networkidle")
问题2:中文路径乱码
原因:URL编码问题
解决:
from urllib.parse import quote
encoded_path = quote(path, safe='/')
扩展应用场景
这套AI辅助开发的方法论可以应用于:
-
1. 电商数据采集:商品信息、价格监控 -
2. 社交媒体分析:微博、知乎内容抓取 -
3. 新闻聚合:多源新闻自动采集 -
4. 招聘信息整合:各大招聘网站数据汇总 -
5. 学术资源收集:论文、专利数据抓取
总结
AI辅助编程不是替代程序员,而是:
-
1. 提升效率:将重复性工作自动化 -
2. 降低门槛:让非专业人员也能完成数据抓取 -
3. 优化思路:AI提供的解决方案可能比人工更优 -
4. 快速迭代:从想法到实现只需几分钟
核心流程:
需求描述 → 投喂HTML → 获得JS代码 → 转为Playwright → 测试优化 → 完成
掌握这套方法,你也能在几十分钟内完成原本需要数小时的数据抓取项目!
作者声明:本文所述方法仅用于学习交流,请遵守网站robots.txt协议和相关法律法规,不要对目标网站造成过大压力。