🚀《拒绝调包侠!从零手写 Python 目录扫描器:v0

摘要:在网络安全学习中,我们习惯了使用 Dirsearch、Gobuster 等成熟工具。但你是否想过,如果让你从零开始写一个目录扫描器,你会遇到哪些坑?本文不直接甩代码,而是复盘我开发 DirScanner-Lab 的全过程。从 v0.1 的单线程龟速,到 v0.4 的多线程专业版,每一个 .1 的版本号背后,都是一个真实的报错和一个具体的解决方案。

🌟 项目源码已开源https://github.com/LanSang11/DirScanner-Lab


📖 前言:为什么要重复造轮子?

刚开始学渗透测试时,我也觉得“调包”很香:import requests,几行代码就能扫目录。直到有一次,我想修改字典的编码规则,却发现看不懂别人几千行的源码;想增加多线程,结果程序直接死锁卡住。

那一刻我决定:扔掉现成工具,自己从头写一个!

这个项目被我命名为 **DirScanner-Lab**,寓意是一个不断试错、不断进化的实验室。它不是最完美的工具,但它记录了一个新手如何一步步解决真实问题的全过程。


🐢 阶段一:v0.1 单线程原型 —— “慢得让人怀疑人生”

初衷:用最简单的逻辑实现功能,验证思路。
代码逻辑:读取字典 -> requests.get -> 打印结果。

# v0.1 核心逻辑伪代码
for path in open('dict.txt'):
    resp = requests.get(url + path)
    if resp.status_code == 200:
        print(f"[+] Found: {path}")

❌ 遇到的真实痛点

  1. 效率极低:目标服务器响应慢或网络波动时,程序会傻等几十秒。扫描 1000 个路径需要半小时,简直是在“数羊”。
  2. 体验差:屏幕长时间无输出,我经常以为程序死了,结果它还在跑。

💡** 我的思考**:网络 IO 是瓶颈,必须引入并发机制。但这一步,让我踩了后面两个大坑。

(
)


💥 阶段二:v0.2 编码崩溃 —— “为什么读到一半报错了?”

改进:为了扫得更全,我换上了一个 45MB 的大字典(包含中文路径)。
** 遇到的报错**:
程序跑到第 3421 行突然崩溃,控制台一片红:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 10: invalid continuation byte

🔍 原因分析

网上的字典来源复杂,有的用 UTF-8,有的用 GBK(中文 Windows 常见)。我的代码只写了 encoding='utf-8',一旦遇到 GBK 字符就直接崩溃。

✅ 解决方案 (v0.2)

我引入了一个“尝试多种编码”的机制。不再假设字典是某种编码,而是按顺序尝试 utf-8 -> gbk -> latin-1,直到成功读取。

# v0.2 核心改进代码片段
encodings = ['utf-8', 'gbk', 'latin-1']
for enc in encodings:
    try:
        with open(file, encoding=enc) as f:
            lines = f.readlines()
            print(f"✅ 成功使用 {enc} 编码读取字典")
            break
    except UnicodeDecodeError:
        continue

结果:无论字典是什么“奇葩”编码,都能顺利加载。这让我明白:健壮性比功能更重要。


🧵 阶段三:v0.3 多线程死锁 —— “为什么程序跑完了却不退出?”

改进:引入 threadingqueue,开启 20 个线程并行扫描。
** 效果**:速度瞬间提升 20 倍!原本半小时的任务,现在一分钟搞定。

❌ 遇到的诡异现象

这是我最头疼的一个 Bug。
扫描进度明明显示 100%,所有任务都跑完了,但程序卡住不动,光标一直闪烁,必须手动按 Ctrl+C 才能看到统计结果。

🔍 深度调试

通过查阅文档和断点调试,我发现问题出在 queue.join()
主线程在等待所有任务调用 task_done()。如果在 scan_path 函数中,线程在 get() 之后、task_done() 之前发生了未捕获的异常(比如网络超时),那么 task_done() 就永远不会执行。队列认为还有任务没完成,主线程就永远等待。

✅ 解决方案 (v0.3)

使用 try...finally 结构,强制确保 task_done() 在任何情况下(包括异常)都会被执行。

# v0.3 关键修复代码
while True:
    try:
        path = q.get(timeout=0.5)
    except queue.Empty:
        break
    try:
        # 执行扫描逻辑
        requests.get(...)
    except Exception as e:
        # 记录错误,但不中断
        pass
    finally:
        q.task_done() # 无论成败,必须标记完成!

结果:程序扫描结束后自动优雅退出,不再卡死。这个 Bug 让我对多线程的生命周期有了深刻理解。

(
)


🚀 阶段四:v0.4 专业测试版 —— “像黑客工具一样易用”

到了 v0.4,我不再满足于“能跑”,而是追求“好用”。

❌ 遗留问题

  1. 参数硬编码:改 URL、线程数都要改代码,太 Low 了。
  2. 无效扫描:字典里包含 # 开头的注释行,导致大量无效请求。
  3. 无反馈:不知道扫了多少,还剩多少。

✅ 终极方案

  1. CLI 交互:引入 argparse,支持 -u, -t, --limit 等参数。
  2. 智能过滤:自动跳过注释行和特殊字符。
  3. 实时进度条:利用 \r 覆盖当前行,实时显示 进度% | 速度 p/s | 发现数

🎯** 最终运行效果**:

python my_scanner_pro_v0.4.py -u http://target.com -t 20 --limit 2000
📂 正在加载字典... ✅ 有效路径: 2000, 跳过: 150 (编码: utf-8)
⏳ 进度: 1000/2000 (50.00%) | 发现: 3 | 速度: 21.5 p/s
[+] 发现: http://target.com/admin (状态码: 200)

📥 源码获取与扩展

本项目的所有代码(从 v0.1 到 v0.4 的演变过程)都已整理并在 GitHub 开源。

👉 仓库地址: https://github.com/LanSang11/DirScanner-Lab

🛠️ 如何运行?

  1. 克隆项目
git clone https://github.com/LanSang11/DirScanner-Lab.git
cd DirScanner-Lab
  1. 安装依赖
pip install requests
  1. 运行测试 (使用内置的小字典):
python my_scanner_pro_v0.4.py -u http://example.com --limit 100

⚠️** 关于字典的说明
为了保持仓库轻量及合规,
GitHub 上仅提供了 **dict_sample.txt** (测试用小字典)**。
如需进行大规模扫描,请自行准备字典文件(如 dirb, rockyou 等),并通过 -d 参数指定。这也是为什么我将项目命名为 Lab —— 希望你在这里加入自己的实验数据。

(👉 此处建议你自己加一段话:例如“大家在运行如果遇到某某问题,欢迎在 GitHub 提 Issue,我们一起讨论”,这样显得更亲切)


📝 总结与展望

从 v0.1 到 v0.4,这个小小的扫描器不仅提升了我的 Python 编程能力,更让我理解了“工具的本质是解决具体问题”

  • v0.1 教会我基础逻辑;
  • v0.2 教会我处理异常和编码;
  • v0.3 让我攻克了多线程并发难题;
  • v0.4 则让我学会了如何设计用户友好的接口。

接下来,我计划在这个项目中加入正则匹配敏感信息代理池支持的功能。如果你对某个功能感兴趣,或者有更好的优化建议,欢迎去我的 GitHub 仓库 DirScanner-Lab 提 Issue 或 PR!

拒绝做“调包侠”,让我们一起动手,造出更适合自己的轮子!


免责声明:本工具仅供网络安全学习与研究使用,严禁用于未授权的攻击行为。使用者需自行承担法律责任。


posted @ 2026-03-24 00:12  LanSame  阅读(1)  评论(0)    收藏  举报