Web 渗透测试之沙场点兵:信息收集篇,从零基础到精通,收藏这篇就够了!

Web 渗透测试之沙场点兵:信息收集篇(超详细)

1、信息收集:渗透测试的“兵马俑”

信息收集

在渗透测试的战场上,信息收集就是那排兵布阵前的“摸底”,是最最关键的一环。在这个阶段,我们要像侦探一样,尽可能多地挖掘目标组织的“秘密”。正所谓“知己知彼,百战不殆”,咱们对测试目标了解得越透彻,渗透测试这仗就打得越漂亮!

常见的信息收集有哪些?

子域名查询、whois 信息挖掘、IP 段“扫荡”、开放端口“侦察”、目录“寻宝”、指纹识别、旁站与 C 段“迂回”、敏感文件与目录“暗访”、WAF“探底”、整站分析(操作系统是 Linux 还是 Windows?Web 容器是 Apache、Nginx、Tomcat 还是 IIS?数据库是 MySQL、SQL Server、Access 还是 Oracle?脚本类型是 PHP、JSP、ASP/ASPX 还是 Python?)

信息收集的方式

主动信息收集:就像直接敲门拜访,我们会直接访问、扫描网站,流量会流经“第三方网站”。

被动信息收集:好比请“中间人”打听消息,我们会利用第三方的服务来访问目标网站,比如 Google 搜索、FOFA 等。

2、域名信息收集:顺藤摸瓜的“藤”

什么是域名

域名嘛,就好比是互联网世界的“门牌号”,也就是网站网址的“昵称”。这些“昵称”由一串字符组成,通常以“.com”、“.net”、“.cn”等结尾。

域名是由一串英文字母和数字组成的,中间用“.”隔开,形成一个独一无二的“访问地址”,比如 a.baidu.com。

什么是域名系统

域名系统(Domain Name System,简称 DNS)可是互联网的“核心管家”之一,它能把域名和 IP 地址“对上号”,就像一个分布式的“通讯录”。有了域名系统,咱们上网就方便多了,再也不用记那些又长又难记的 IP 地址了。此外,域名系统还提供了域名注册、域名解析等“一条龙”服务。简单来说,它就是一个把域名“翻译”成 IP 地址的“翻译官”

域名解析

域名是为了方便大家记忆而专门打造的一套“地址翻译系统”。用户想在互联网上“串门”,最终还是得通过 IP 地址来访问服务器。域名解析就是把域名“还原”成 IP 地址的过程,这个“翻译”工作由 DNS 服务器完成。

子域名收集:扩大战果的“侦察兵”

什么是子域名

收集子域名,目的就是为了“广撒网”,获取更多的“资产情报”。子域名也就是二级域名,好比“总店”下面的“分店”,比如 a.baidu.com。

为什么要收集子域名

如果目标的“地盘”太大,直接从“总店”下手显然不明智,因为“总店”通常都是“戒备森严”的。这时候,我们可以选择“曲线救国”,先从目标的某个“分店”下手,然后再想办法迂回接近“核心目标”。

1、常见的域名“侦察”工具

Layer 子域名挖掘机、subDomainsBrute、oneforall、dnsmaper、K8、wydomain、Sublist3r、Maltego 等

Layer 子域名挖掘机

这款工具江湖人称“断网挖掘机”,咱们就简单了解一下,知道有这么个“神器”就行。

subDomainsBrute

SubDomainsBrute 是一款“暴力破解”子域名的工具。它会用“字典”里的各种组合来尝试可能的子域名,并通过 DNS 解析来确定这些子域名是不是“真实存在”的。

在 Kali 中使用:
下载:git clone https://github.com/lijiejie/subDomainsBrute.git
使用:python3 subDomainsBrute.py -t 10 域名 (-t 指定“线程”数量)

2、在线工具集:一站式“情报中心”
  1. 1 DNSdumpster: https://dnsdumpster.com/

  2. 2 潮汐指纹识别: http://finger.tidesec.com/

  3. 3.站长工具: http://tool.chinaz.com/subdomain/

  4. 4 在线子域名爆破: http://z.zcjun.com/

3、在线子域名查询:搜索引擎的“隐藏技能”

1、FOFA 搜索子域名

地址:https://fofa.info
语法:domain="bilibili.com"

2、利用搜索引擎发现子域名

利用 Google 搜索语法 site:bilibili.com 查询

Whois 信息收集:域名背后的“蛛丝马迹”

什么是 Whois

Whois 就像一个“域名信息查询台”,可以用来查询域名的 IP 地址、所有者等信息。我们可以用它来查域名有没有被注册,以及注册域名的详细信息(比如域名所有人、域名注册商等)。

为什么要收集 Whois

通过 Whois 收集,我们可以挖到域名注册者的姓名、手机号、邮箱地址等信息。一般来说,对于中小型网站,域名注册者就是网站管理员。我们可以尝试“社工”、套路、或者查查他是不是还注册了其他域名,来扩大我们的“攻击范围”。

Whois 信息收集重点关注:注册商、注册人、邮件、DNS 解析服务器、注册人联系电话。

Web 接口查询:在线“情报站”

常见的信息收集网站包括:

  • Whois 站长之家:http://whois.chinaz.com
  • 国外的 whois:https://www.whois.com
  • 微步在线:https://x.threatbook.cn/
  • 阿里云中国万网:https://whois.aliyun.com/
  • Whois Lookup 查找目标网站所有者信息:http://whois.domaintools.com/
  • Netcraft Site Report 显示目标网站使用的技术:http://toolbar.netcraft.com/site_report?url=
  • Robtex DNS 查询显示关于目标网站的全面的 DNS 信息:https://www.robtex.com/
  • 全球 Whois 查询:https://www.whois365.com/cn/
  • 站长工具爱站查询:https://whois.aizhan.com/
  • 爱站网 ping 检测\IP 反查域:https://dns.aizhan.com/

备案信息查询:网站的“户口本”

网站备案就像给网站办“户口”,是根据国家法律法规,网站所有者需要向国家有关部门申请的。这是国家信息产业部对网站的一种管理,主要是为了防止有人在网上搞“非法勾当”。主要针对国内网站,如果网站“落户”在其他国家,就不需要备案了。

IPC 备案查询方法包括:

  • http://icp.chinaz.com/
  • https://www.beian88.com/
  • https://www.tianyancha.com/
  • http://www.beianbeian.com/
  • 以及企查查、天眼查、小蓝本等,可以查询更多“内幕”。

域名反查 IP 站长工具:https://ip.tool.chinaz.com/

3、CDN 信息收集:网站的“影分身”

什么是 CDN

CDN 就是“缓存服务器”,它会把网站的静态资源(比如图片、CSS、JS 文件等)“复制”一份,放到离用户更近的服务器上,这样用户访问网站时就不用“长途跋涉”了,速度更快,体验更好。

从图中可以看到,如果没有 CDN,我们得到的 IP 应该是网站的“真身”IP。但如果有了 CDN,我们得到的 IP 可能就是 CDN 服务器的 IP 地址,也就是网站的“影分身”。

如何检测是否存在 CDN:火眼金睛辨“真身”

1、采用多地点 ping:让“影分身”无处遁形

https://www.17ce.com/

http://ping.chinaz.com

2、ping 和 ip138 结合起来进行辅助判断:双管齐下更“靠谱”

如果 ping 和 ip138 查到的 IP 地址一样,那基本可以确定没有 CDN。反之,则很可能有 CDN。

3、命令:nslookup 判断:专业工具来“验明正身”

nslookup(Name Server Lookup)是一种网络管理命令,可以用来查询 DNS 服务器的域名、IP 或其他 DNS 记录信息。

绕过 CDN 查找真实 IP 地址:斗智斗勇找“真身”
  • 内部邮箱:一般来说,邮件系统都在“自家地盘”上,没经过 CDN。我们可以通过注册或者 RSS 订阅收到的邮件来查找。(前提是目标用的是自己的邮件服务器)
  • 子域名:一般网站的“总店”访问量太大,需要挂 CDN,而“分店”可能就没那么“讲究”了。https://ping.chinaz.com/
  • 国外访问:一般来说,国内的 CDN 只针对国内用户,国外的用户可能就“享受”不到这个“待遇”了。https://tools.ipip.net/cdn.php
  • 查询历史 DNS 记录:看看 IP 与域名绑定的“老黄历”,可能会有使用 CDN 之前的记录。https://viewdns.info/
  • 国外查 IP:https://get-site-ip.com/

4、端口扫描:网络世界的“敲门砖”

什么是端口

端口就像计算机或其他设备与外界“沟通交流”的“窗口”。它可以是物理上的“插孔”(比如 USB 端口),也可以是逻辑上的“抽象概念”。

  • 物理端口:也叫接口,比如 USB 端口,用来“插”各种设备的。
  • 虚拟端口:一般指 TCP/IP 协议中的端口,比如我们上网用的 80 端口、21 端口、23 端口等。

计算机有 0-65535 个端口,这么多“门”,总有一扇适合你!

为什么要进行端口探测

有些“危险”的端口如果开着,我们就可以尝试“入侵”了。比如 445、3306、22、3389、6379,我们可以利用这些端口存在的“漏洞”或者尝试“暴力破解”,来“攻城略地”。

常见的端口

端口号端口说明
22SSH 远程连接
23Telnet 远程连接
3389远程桌面连接
3306MySQL 数据库
1521Oracle 数据库
6379Redis 数据库
25SMTP 邮件服务
80/443/8080常见的 Web 服务端口
53DNS 域名系统

端口探测方法

Nmap:网络扫描的“瑞士军刀”

nmap(Network Mapper)是一款开源免费的、专门针对大型网络的端口扫描工具。nmap 可以“侦察”目标主机是否在线、主机端口开放情况、检测主机运行的服务类型及版本信息、检测操作系统与设备类型等。

nmap 主要功能

  1. 检测主机是否在线
  2. 扫描指定主机/主机列表端口开放状态
  3. 检测主机运行服务类型及版本等等

利用可视化界面 Zenmap 来进行扫描

指令用法
namp url/ip最常用的扫描指令
nmap –p 80,22 url/ip自定义想扫描的端口
nmap –p 1-255 url/ip自定义扫描的端口范围
nmap –r url/ip随机扫描端口
nmap –O –fuzzy url/ip推测操作系统
nmap -sV url/ip版本探测
nmap -A -T4 url/ip-A 选项启用了操作系统检测(-O) 和版本扫描(-sV);-T4 使用时间模板 4,速度更快,但也更容易被发现

在线工具扫描:方便快捷的“云端侦察”

站长工具 https://tool.chinaz.com/port/

5、目录扫描:网站结构的“透视镜”

在渗透测试中,探测 Web 目录结构和隐藏的敏感文件可是“必修课”。通过目录扫描,我们可以找到网站的后台登录、文件上传等“重要入口”,甚至可能扫出网站的“源代码”,从而进行“白盒审计”。

目录扫描工具

御剑、Dirsearch、awvs、DirBuster、dirmap、Webdirscan

6、指纹识别:网站身份的“验真”

指纹识别介绍

每个网站都有自己的“独特标识”,我们一般通过网站 CMS 识别、计算机操作系统识别以及 Web 容器识别来“验明正身”。

指纹识别的目的

在渗透测试中,对目标服务器进行指纹识别,识别出相应的 Web 容器或者 CMS,才能“对症下药”,查找与其相关的漏洞,然后利用这些漏洞进行渗透测试。

CMS 介绍

CMS(Content Management System)又称“整站系统”或“文章系统”,是用来管理网站内容的。简单来说,CMS 就是一套可以快速搭建网站的“源码”。因为这种 CMS 是开源的,可能存在一些“通杀”的漏洞。如果我们发现目标网站使用了 CMS 建站,就可以尝试用这些“通杀”漏洞来“一招制敌”。

常见的 CMS

dedecms(织梦)、phpcms、帝国 cms、shopex、ECShop、PHPWind、Discuz

指纹识别方法

线上识别:在线“情报库”
  • 微步社区:https://x.threatbook.cn/
  • 潮汐识别:http://finger.tidesec.com/
  • 云悉指纹:https://www.yunsee.cn/
  • wappalyzer 插件:https://www.wappalyzer.com/
  • WhatWeb:https://www.whatweb.net/
  • 测试网站:http://www.superwing.com.cn/ 识别 CMS

GitHub 上面的工具:开源“情报站”
  • Webfinger 指纹识别,2000+ 条指纹数据:https://github.com/se55i0n/Webfinger
  • CMSeek,超过 170 个 CMS 的基本 CMS 检测:https://github.com/Tuhinshubhra/CMSeek
常见工具

whatweb 网站探测,这款工具 Kali 自带

whatweb http:域名/ip

wappalyzer 浏览器插件工具

7、旁站扫描:“隔壁老王”也别放过

“旁站”一般指同一 IP 或者域名在同一台服务器上的其他网站,目的也是为了找到更多的“资产”。

旁站就是找和目标网站在同一台服务器下的某个“邻居”。同服务器就意味着同 IP,所以只要找到 IP 相同的网站就行了。它们不一定是同一家公司的,但“远亲不如近邻”,说不定能从“邻居”那里找到突破口呢!

通过在线工具来查询旁站

  • 站长之家同 IP 查询:https://stool.chinaz.com/same
  • wenscan: https://www.webscan.cc/

8、C 段嗅探:网络“邻居”大搜查

什么是 C 段

IP 地址有四个段,分为 A、B、C、D 四段。比如说 192.168.0.1,A 段是 192,B 段是 168,C 段是 0,D 段是 1。

什么是 C 段嗅探

拿下目标服务器同一 C 段中的其他服务器,也就是说拿下 D 段 1-255 中的一台服务器。比如说 192.168.0.1 这台主机“啃”不动,那么我们可以尝试从 C 段“下手”,探测 192.168.0.2-255 下存在的主机进行渗透。

C 段:同网段不同服务器的渗透方案,更多的是针对内网的渗透。

nmap 进行扫描

nmap -sn -PE -n ip/24
-sn 不扫描端口
-PE ICMP 扫描(ping 服务器的时候就是用的 ICMP 协议)
-n 不进行 DNS 解析

fofa

https://fofa.info/
ip="ip/24"

9、敏感内容泄露:网站的“小秘密”

敏感信息包括但不限于:口令、密钥、证书、会话标识、License、隐私数据、授权凭据、个人数据等、程序文件、配置文件、日志文件、备份文件、敏感路径等。

robots.txt

robots.txt 文件里写了“反爬虫”策略,介绍了哪些路径可以爬取,哪些路径不能爬取。那么,这里面可能就藏着“猫腻”,比如后台、备份文件路径等等。

目录浏览

目录浏览(目录遍历)漏洞是因为网站存在配置缺陷,导致网站的很多“隐私”文件和目录“曝光”,比如数据库备份文件、配置文件等。攻击者利用这些信息可以更容易地“拿下”网站权限,导致网站“失守”。

备份文件泄露

网站遗留的过时文件、备份页面、开发文件残留的测试文件等。一旦泄露,测试人员就可以分析出网站的大体结构,甚至推算出网站的“源代码”。
比如:sql 备份文件则直接泄露用户数据、密码等信息,后果不堪设想!

报错页面敏感信息泄漏

服务器代码信息、数据库连接信息、泄露物理路径、泄露网站源代码

黑客/网络安全学习路线

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

网络安全学习资源分享:

下面给大家分享一份2025最新版的网络安全学习路线资料,帮助新人小白更系统、更快速的学习黑客技术!

一、2025最新网络安全学习路线

一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

在这里插入图片描述

L1级别:网络安全的基础入门

L1阶段:我们会去了解计算机网络的基础知识,以及网络安全在行业的应用和分析;学习理解安全基础的核心原理,关键技术,以及PHP编程基础;通过证书考试,可以获得NISP/CISP。可就业安全运维工程师、等保测评工程师。

在这里插入图片描述

L2级别:网络安全的技术进阶

L2阶段我们会去学习渗透测试:包括情报收集、弱口令与口令爆破以及各大类型漏洞,还有漏洞挖掘和安全检查项目,可参加CISP-PTE证书考试。

在这里插入图片描述

L3级别:网络安全的高阶提升

L3阶段:我们会去学习反序列漏洞、RCE漏洞,也会学习到内网渗透实战、靶场实战和技术提取技术,系统学习Python编程和实战。参加CISP-PTE考试。

在这里插入图片描述

L4级别:网络安全的项目实战

L4阶段:我们会更加深入进行实战训练,包括代码审计、应急响应、红蓝对抗以及SRC的挖掘技术。并学习CTF夺旗赛的要点和刷题

在这里插入图片描述

整个网络安全学习路线L1主要是对计算机网络安全的理论基础的一个学习掌握;而L3 L4更多的是通过项目实战来掌握核心技术,针对以上网安的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。

二、技术文档和经典PDF书籍

书籍和学习文档资料是学习网络安全过程中必不可少的,我自己整理技术文档,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,(书籍含电子版PDF)

在这里插入图片描述

三、网络安全视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的网安视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

在这里插入图片描述

四、网络安全护网行动/CTF比赛

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

在这里插入图片描述

五、网络安全工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。在这里插入图片描述

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了技术之后,就需要开始准备面试,我们将提供精心整理的网安面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

在这里插入图片描述

img

**读者福利 |** 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

<think>我们只测试两个图片:'久经沙场.png'和'零.png' 由于之前提供的偏移值可能不准确,我们需要重新调整测试代码,确保能捕获到正确的区域 我们将使用您提供的偏移值:久经沙场.png: (3,24,86,34) 和 零.png: (64, -57, 104, 32) 注意:负偏移值表示向左或向上偏移 我们将创建一个测试类,专门用于测试这两张图片的偏移值配置,并尝试识别数字 由于我们只测试两张图片,我们可以单独为它们编写测试逻辑,并保存中间截图以便调试 </think>我将创建一个专门测试脚本,针对您指定的两个图片配置进行测试:久经沙场.png (3,24,86,34) 和 零.png (64, -57, 104, 32)。以下是完整的测试代码: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import sys import time import cv2 import numpy as np import pyautogui import pytesseract from PIL import Image from datetime import datetime from pathlib import Path import tkinter as tk from tkinter import filedialog # 配置基础路径 - 请修改为您的实际路径 BASE_DIR = Path(r"D:\yunfe\手机悠悠") # 配置Tesseract路径 def find_tesseract_path(): potential_paths = [ r'C:\Program Files\Tesseract-OCR\tesseract.exe', r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe', '/usr/bin/tesseract', '/usr/local/bin/tesseract' ] for path in potential_paths: if os.path.exists(path): return path env_path = os.getenv('TESSERACT_PATH') if env_path and os.path.exists(env_path): return env_path root = tk.Tk() root.withdraw() path = filedialog.askopenfilename( title="选择 Tesseract-OCR 可执行文件", filetypes=[("Executable files", "*.exe"), ("All files", "*.*")] ) root.destroy() if path and os.path.exists(path): return path raise FileNotFoundError("无法找到 Tesseract-OCR 路径,请手动配置") try: pytesseract.pytesseract.tesseract_cmd = find_tesseract_path() print(f"✅ Tesseract 路径配置成功: {pytesseract.pytesseract.tesseract_cmd}") except Exception as e: print(f"❌ Tesseract 路径配置失败: {e}") sys.exit(1) class FocusedOffsetTester: def __init__(self, base_path): self.base_path = Path(base_path) self.debug_dir = self.base_path / "offset_debug" / datetime.now().strftime("%Y%m%d_%H%M%S") os.makedirs(self.debug_dir, exist_ok=True) # 只测试指定的两个图片配置 self.test_config = { '久经沙场.png': (3, 24, 86, 34), '零.png': (64, -57, 104, 32), } # 验证所有图片存在 self.verify_images() print("\n" + "="*70) print("📋 测试配置 (仅针对指定图片)") print("="*70) for img, config in self.test_config.items(): print(f" {img}: offset_x={config[0]}, offset_y={config[1]}, width={config[2]}, height={config[3]}") print("="*70 + "\n") def verify_images(self): """验证测试图片是否存在""" print("\n🔍 验证测试图片...") missing_files = [] for img_name in self.test_config.keys(): img_path = self.base_path / img_name if not img_path.exists(): missing_files.append(img_name) print(f"❌ 图片不存在: {img_path}") if missing_files: print("\n⚠️ 目录中的图片列表:") for f in self.base_path.glob('*.png'): print(f" - {f.name}") raise FileNotFoundError(f"缺少测试图片: {', '.join(missing_files)}") print("✅ 所有测试图片都存在") def capture_target_area(self, image_name): """捕获指定图片的目标区域""" config = self.test_config[image_name] offset_x, offset_y, width, height = config print(f"\n🔍 定位图片: {image_name}") # 尝试定位模板图片 img_path = self.base_path / image_name template_location = None attempts = 5 for attempt in range(attempts): try: print(f" 尝试 {attempt+1}/{attempts}...") template_location = pyautogui.locateOnScreen( str(img_path), confidence=0.7, grayscale=True ) if template_location: break time.sleep(0.5) except Exception as e: print(f" 定位错误: {e}") if template_location is None: print(f"❌ 无法定位图片: {image_name}") return None, None, None print(f"✅ 定位成功: {template_location}") # 计算目标区域坐标 target_left = template_location.left + offset_x target_top = template_location.top + offset_y # 确保区域在屏幕内 screen_width, screen_height = pyautogui.size() if target_left < 0: target_left = 0 if target_top < 0: target_top = 0 if target_left + width > screen_width: width = screen_width - target_left if target_top + height > screen_height: height = screen_height - target_top print(f"🎯 目标区域: ({target_left}, {target_top}), {width}x{height}") # 截取目标区域 region = (target_left, target_top, width, height) try: screenshot = pyautogui.screenshot(region=region) screenshot_np = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR) # 保存截图 debug_path = self.debug_dir / f"capture_{image_name}" cv2.imwrite(str(debug_path), screenshot_np) print(f"📸 区域截图保存到: {debug_path}") return screenshot_np, template_location, region except Exception as e: print(f"💥 截图失败: {e}") return None, None, None def visualize_capture(self, image_name, template_location, region, screenshot): """可视化捕获区域""" # 获取屏幕截图 full_screen = pyautogui.screenshot() full_screen_np = cv2.cvtColor(np.array(full_screen), cv2.COLOR_RGB2BGR) # 绘制模板定位框(红色) template_box = ( template_location.left, template_location.top, template_location.width, template_location.height ) cv2.rectangle( full_screen_np, (template_box[0], template_box[1]), (template_box[0] + template_box[2], template_box[1] + template_box[3]), (0, 0, 255), # 红色 2 ) # 绘制目标区域框(绿色) target_box = region cv2.rectangle( full_screen_np, (target_box[0], target_box[1]), (target_box[0] + target_box[2], target_box[1] + target_box[3]), (0, 255, 0), # 绿色 2 ) # 绘制从模板中心到目标区域中心的连线(黄色) template_center = ( template_box[0] + template_box[2] // 2, template_box[1] + template_box[3] // 2 ) target_center = ( target_box[0] + target_box[2] // 2, target_box[1] + target_box[3] // 2 ) cv2.line( full_screen_np, template_center, target_center, (0, 255, 255), # 黄色 2 ) # 添加说明文字 cv2.putText( full_screen_np, f"Template: {image_name}", (template_box[0], template_box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1 ) cv2.putText( full_screen_np, f"Target: ({target_box[0]},{target_box[1]}) {target_box[2]}x{target_box[3]}", (target_box[0], target_box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 ) # 保存可视化图片 vis_path = self.debug_dir / f"visual_{image_name}" cv2.imwrite(str(vis_path), full_screen_np) print(f"👁️ 可视化保存到: {vis_path}") # 保存目标区域放大图 roi_img = full_screen_np[ target_box[1]:target_box[1] + target_box[3], target_box[0]:target_box[0] + target_box[2] ] roi_path = self.debug_dir / f"roi_{image_name}" cv2.imwrite(str(roi_path), roi_img) return full_screen_np def enhance_text_region(self, image): """增强文本区域""" try: # 转为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用CLAHE增强对比度 clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)) enhanced = clahe.apply(gray) # 自适应阈值处理 binary = cv2.adaptiveThreshold( enhanced, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2 ) # 形态学操作去除噪点 kernel = np.ones((2, 2), np.uint8) cleaned = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) return cleaned except Exception as e: print(f"💥 文本增强失败: {e}") return image def recognize_digits(self, image, image_name): """识别图像中的数字""" # 预处理图像 processed = self.enhance_text_region(image) # 保存预处理图像 preprocess_path = self.debug_dir / f"preprocessed_{image_name}" cv2.imwrite(str(preprocess_path), processed) # 转换为PIL图像 img_pil = Image.fromarray(processed) # OCR识别配置 configs = [ ('psm6', r'--psm 6 -c tessedit_char_whitelist=0123456789.', '块模式'), ('psm7', r'--psm 7 -c tessedit_char_whitelist=0123456789.', '单行模式'), ('psm8', r'--psm 8 -c tessedit_char_whitelist=0123456789.', '单词模式'), ('psm10', r'--psm 10 -c tessedit_char_whitelist=0123456789.', '单字符模式'), ('digits', r'--psm 7 digits', '数字专用模式'), ] print("\n🔤 OCR识别尝试:") results = [] for config_id, config_str, config_desc in configs: try: text = pytesseract.image_to_string(img_pil, config=config_str).strip() # 移除所有非数字字符(保留小数点) cleaned = ''.join(filter(lambda c: c.isdigit() or c == '.', text)) print(f" {config_desc} ({config_id}): 原始: '{text}' | 清理后: '{cleaned}'") # 尝试解析为数字 if cleaned: try: # 检查是否是小数形式 if '.' in cleaned: num_value = float(cleaned) else: # 假设是整数,转换为小数 num_value = float(cleaned) / 100 results.append({ 'config': config_id, 'desc': config_desc, 'text': text, 'cleaned': cleaned, 'value': num_value }) except ValueError: results.append({ 'config': config_id, 'desc': config_desc, 'text': text, 'cleaned': cleaned, 'value': None }) except Exception as e: print(f" {config_desc} 识别错误: {e}") # 选择最佳结果 best_result = None for res in results: if res['value'] is not None: # 优先选择有小数点的结果 if '.' in res['cleaned']: best_result = res break # 否则选择第一个有效结果 if best_result is None: best_result = res return best_result, results def highlight_digits(self, image, text_result): """在图像上高亮显示识别到的数字""" if text_result is None: return image # 创建带有OCR结果的图像 marked_image = image.copy() cv2.putText( marked_image, f"识别结果: {text_result['cleaned']} -> {text_result['value']}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), # 绿色 2 ) cv2.putText( marked_image, f"配置: {text_result['config']} ({text_result['desc']})", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), # 黄色 1 ) return marked_image def run_test(self): """运行所有测试""" results = {} print("\n" + "="*70) print("🚀 开始偏移值配置测试") print("="*70) for img_name, config in self.test_config.items(): print(f"\n🔧 测试 [{img_name}] ...") print(f" 偏移值配置: offset_x={config[0]}, offset_y={config[1]}, width={config[2]}, height={config[3]}") # 1. 捕获目标区域 screenshot, template_loc, region = self.capture_target_area(img_name) if screenshot is None: print(f"❌ 测试失败: 无法捕获 {img_name} 的目标区域") results[img_name] = {'status': 'error', 'message': 'Capture failed'} continue # 2. 可视化捕获区域 self.visualize_capture(img_name, template_loc, region, screenshot) # 3. 尝试识别数字 best_result, all_results = self.recognize_digits(screenshot, img_name) # 4. 处理结果 if best_result and best_result['value'] is not None: print(f"✅ 识别成功: {best_result['value']:.4f} (使用 {best_result['config']} 配置)") status = 'success' # 创建带标记的图像 marked_img = self.highlight_digits(screenshot, best_result) marked_path = self.debug_dir / f"result_{img_name}" cv2.imwrite(str(marked_path), marked_img) print(f"📝 标记结果保存到: {marked_path}") else: print("❌ 识别失败: 未提取到有效数字") status = 'fail' # 5. 保存结果 results[img_name] = { 'status': status, 'best_result': best_result, 'all_results': all_results, 'screenshot_path': self.debug_dir / f"capture_{img_name}" } # 添加短暂延迟 time.sleep(1) # 打印汇总结果 print("\n" + "="*70) print("📊 测试结果汇总") print("="*70) for img_name, result in results.items(): config = self.test_config[img_name] print(f"\n图片: {img_name}") print(f"配置: offset_x={config[0]}, offset_y={config[1]}, width={config[2]}, height={config[3]}") if result['status'] == 'success': best = result['best_result'] print(f"✅ 识别成功: {best['value']:.4f} (使用 {best['config']} 配置)") print(f" 原始文本: '{best['text']}'") print(f" 处理后文本: '{best['cleaned']}'") elif result['status'] == 'fail': print("❌ 识别失败: 未提取到有效数字") print(" 尝试的OCR配置及结果:") for res in result['all_results']: print(f" {res['config']} ({res['desc']}): '{res['text']}' -> '{res['cleaned']}'") else: print(f"💥 错误: {result['message']}") print("\n" + "="*70) success_count = sum(1 for r in results.values() if r['status'] == 'success') print(f"测试完成: {success_count} 成功 / {len(self.test_config)} 总计") print(f"调试文件保存到: {self.debug_dir}") print("="*70) # 打开调试目录 try: if sys.platform == 'win32': os.startfile(self.debug_dir) elif sys.platform == 'darwin': os.system(f'open "{self.debug_dir}"') else: os
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值