You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
7.5 KiB
173 lines
7.5 KiB
package com.example;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.*;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URL;
|
|
import javax.imageio.ImageIO;
|
|
import net.sourceforge.tess4j.Tesseract;
|
|
import net.sourceforge.tess4j.TesseractException;
|
|
|
|
// ... 其他必要的导入 ...
|
|
|
|
public class CaptchaOCR {
|
|
|
|
// Tesseract data 路径 (tessdata 文件夹所在目录)
|
|
// Windows 示例: "C:\\Program Files\\Tesseract-OCR\\tessdata"
|
|
// Linux/macOS 示例: 通常不需要设置,Tess4J 会自动查找
|
|
private static final String TESSDATA_PATH = "F:\\tool\\Tesseract-OCR\\tessdata"; // 根据你的安装路径修改
|
|
|
|
/**
|
|
* 下载验证码图片
|
|
* @param imageUrl 图片的完整 URL
|
|
* @return 图片的 BufferedImage 对象
|
|
* @throws IOException 如果下载失败
|
|
*/
|
|
public static BufferedImage downloadImage(String imageUrl) throws IOException {
|
|
URL url = new URL(imageUrl);
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
conn.setRequestMethod("GET");
|
|
// 添加 User-Agent 等必要的请求头,模拟浏览器
|
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36");
|
|
// ... 其他头 ...
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
try (InputStream is = conn.getInputStream()) {
|
|
// 将输入流读取到字节数组,ImageIO 从字节数组读取更稳定
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
byte[] buffer = new byte[4096]; // 缓冲区大小,可以调整
|
|
int bytesRead;
|
|
while ((bytesRead = is.read(buffer)) != -1) {
|
|
baos.write(buffer, 0, bytesRead);
|
|
}
|
|
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
|
|
BufferedImage image = ImageIO.read(bais);
|
|
|
|
if (image == null) {
|
|
throw new IOException("Failed to read image from stream. Check image format.");
|
|
}
|
|
return image;
|
|
}
|
|
} else {
|
|
throw new IOException("Failed to download image. HTTP error code: " + responseCode);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 对验证码图片进行预处理 (基础示例:转灰度+二值化)
|
|
* 这是最关键的部分,需要根据验证码样式调整
|
|
* @param originalImage 原始图片
|
|
* @return 预处理后的图片
|
|
*/
|
|
public static BufferedImage preprocessImage(BufferedImage originalImage) {
|
|
// TODO: 这里是图像预处理的重点,需要根据实际验证码样式进行调整和优化
|
|
// 基础处理:转灰度 -> 二值化
|
|
int width = originalImage.getWidth();
|
|
int height = originalImage.getHeight();
|
|
BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
|
|
grayImage.getGraphics().drawImage(originalImage, 0, 0, null);
|
|
|
|
BufferedImage binaryImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
|
|
// 二值化阈值,可能需要调整 (0-255)
|
|
int threshold = 128;
|
|
for (int y = 0; y < height; y++) {
|
|
for (int x = 0; x < width; x++) {
|
|
int gray = grayImage.getRaster().getSample(x, y, 0);
|
|
if (gray < threshold) {
|
|
binaryImage.getRaster().setSample(x, y, 0, 0); // 黑色
|
|
} else {
|
|
binaryImage.getRaster().setSample(x, y, 0, 1); // 白色
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: 更高级的预处理包括:
|
|
// - 去除干扰线、噪点
|
|
// - 字符分割(如果字符粘连)
|
|
// - 倾斜校正
|
|
// - 调整亮度和对比度等
|
|
// 你可能需要引入更专业的图像处理库或算法
|
|
|
|
// 为了调试,可以将预处理后的图片保存下来查看效果
|
|
try {
|
|
File outputfile = new File("preprocessed_captcha.png");
|
|
ImageIO.write(binaryImage, "png", outputfile);
|
|
System.out.println("Preprocessed image saved to " + outputfile.getAbsolutePath());
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return binaryImage; // 返回预处理后的图片
|
|
}
|
|
|
|
/**
|
|
* 使用 Tess4J 识别图片中的文字
|
|
* @param image 待识别的图片 (最好是预处理后的)
|
|
* @return 识别出的字符串
|
|
*/
|
|
public static String recognizeCaptcha(BufferedImage image) {
|
|
Tesseract tesseract = new Tesseract();
|
|
|
|
// 设置 tessdata 路径 (如果 TESSDATA_PATH 已正确设置且 Tesseract 安装正确,这行可能不是必需的,Tess4J 会自动查找)
|
|
// 但显式设置更保险
|
|
if (TESSDATA_PATH != null && !TESSDATA_PATH.isEmpty()) {
|
|
tesseract.setDatapath(TESSDATA_PATH);
|
|
} else {
|
|
System.out.println("TESSDATA_PATH not set. Tess4J will try to find tessdata automatically.");
|
|
}
|
|
|
|
|
|
tesseract.setLanguage("eng"); // 设置识别语言为英文 (通常包含数字)
|
|
// 如果验证码只有数字,可以尝试设置仅识别数字
|
|
// tesseract.setTessVariable("tessedit_char_whitelist", "0123456789");
|
|
|
|
try {
|
|
String result = tesseract.doOCR(image);
|
|
// 清理识别结果,去除空格或换行符等
|
|
result = result.trim().replaceAll("[^0-9a-zA-Z]", ""); // 根据验证码内容调整清理规则
|
|
System.out.println("OCR Result: " + result);
|
|
return result;
|
|
} catch (TesseractException e) {
|
|
System.err.println("Error during OCR: " + e.getMessage());
|
|
return null; // 识别失败
|
|
}
|
|
}
|
|
|
|
// 示例如何在你的爬虫流程中使用
|
|
public static void main(String[] args) {
|
|
String captchaImageUrl = "YOUR_CAPTCHA_IMAGE_URL"; // 从页面解析获取到的验证码图片 URL
|
|
|
|
try {
|
|
// 1. 下载图片
|
|
BufferedImage originalCaptchaImage = downloadImage(captchaImageUrl);
|
|
System.out.println("Image downloaded.");
|
|
|
|
// 2. 预处理图片
|
|
BufferedImage preprocessedImage = preprocessImage(originalCaptchaImage);
|
|
System.out.println("Image preprocessed.");
|
|
|
|
// 3. 识别验证码
|
|
String captchaCode = recognizeCaptcha(preprocessedImage);
|
|
|
|
if (captchaCode != null && !captchaCode.isEmpty()) {
|
|
System.out.println("Recognized CAPTCHA: " + captchaCode);
|
|
// 4. 将 captchaCode 填入 POST 数据中,提交表单
|
|
// ... (你的 ASP.NET WebForms POST 提交代码,将 captchaCode 放到对应的隐藏字段或输入框字段中) ...
|
|
// 例如:postData += "&captchaInputFieldName=" + URLEncoder.encode(captchaCode, StandardCharsets.UTF_8.name());
|
|
// ... 提交 POST 请求 ...
|
|
|
|
} else {
|
|
System.out.println("Failed to recognize CAPTCHA.");
|
|
// 5. 处理识别失败的情况,可能需要重试或记录日志
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
System.err.println("Error downloading or processing image: " + e.getMessage());
|
|
}
|
|
// catch (URISyntaxException e) {
|
|
// System.err.println("Invalid URL: " + e.getMessage());
|
|
// } // 如果你的 downloadImage 方法 throws URISyntaxException
|
|
}
|
|
}
|