下面我将从简单到复杂,分步讲解整个流程和实现方法。

php如何采集有验证码的网页信息
(图片来源网络,侵删)

核心思想

采集带验证码的网页,本质上是在模拟一个真实用户进行登录或操作,你需要:

  1. 第一次访问目标页面:获取初始的Cookie信息(如果网站依赖Session)。
  2. 获取验证码图片:从HTML源码中找到验证码图片的URL,并请求这个图片。
  3. 处理验证码:这是最关键的一步,有几种主流方法。
  4. 提交表单:将你获取的Cookie、用户名、密码和验证码一起提交到服务器。
  5. 采集数据:如果登录成功,你就可以带着有效的Session Cookie去访问需要登录才能看到的页面,并抓取数据。

准备工作:PHP环境

你需要一个能发起HTTP请求和获取HTML的库,PHP自带的 file_get_contents()curl 扩展都可以,但强烈推荐使用 cURL,因为它更强大,能更好地模拟浏览器行为(如设置Header、Cookie、处理重定向等)。

确保你的PHP环境开启了 curl 扩展。


详细步骤与代码示例

我们以一个模拟的登录页面为例,假设其HTML结构如下:

php如何采集有验证码的网页信息
(图片来源网络,侵删)

login_page.html (模拟)

<html>
<head><title>登录</title></head>
<body>
    <form action="login.php" method="post">
        <p>用户名: <input type="text" name="username"></p>
        <p>密码: <input type="password" name="password"></p>
        <!-- 验证码图片 -->
        <p>验证码: <img src="captcha.php" id="captcha_img"></p>
        <p><input type="text" name="captcha_code"></p>
        <p><input type="submit" value="登录"></p>
    </form>
</body>
</html>

获取页面内容和Cookie

访问登录页面,获取HTML源码和服务器返回的Cookie。

<?php
// 1. 初始化 cURL
$ch = curl_init();
// 2. 设置 cURL 选项
$url = 'http://example.com/login_page.html';
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
curl_setopt($ch, CURLOPT_HEADER, true);         // 包含响应头,用于获取Cookie
// 3. 执行请求
$response = curl_exec($ch);
// 4. 检查是否有错误
if (curl_errno($ch)) {
    echo 'cURL Error: ' . curl_error($ch);
    curl_close($ch);
    exit;
}
// 5. 分离响应头和响应体
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header_content = substr($response, 0, $header_size);
$body_content = substr($response, $header_size);
// 6. 从响应头中提取 Set-Cookie
// 注意:这里是一个简化的提取,实际中可能需要更复杂的解析
preg_match_all('/Set-Cookie: (.*?);/i', $header_content, $matches);
$cookies = $matches[1];
// 将Cookie字符串转换为cURL可用的格式
$cookie_string = implode('; ', $cookies);
echo "获取到的页面内容:\n" . $body_content . "\n\n";
echo "获取到的Cookie:\n" . $cookie_string . "\n";
// 7. 关闭 cURL
curl_close($ch);
?>

获取验证码图片

从上一步获取的HTML中,我们可以用正则表达式或DOM解析器找到验证码图片的URL (captcha.php),然后再次使用cURL请求它。

注意:请求验证码时,必须带上第一步获取的Cookie,因为服务器通常用Cookie来关联你的会话和验证码。

php如何采集有验证码的网页信息
(图片来源网络,侵删)
// 假设 $cookie_string 已经从上一步获取
// 假设我们从HTML中解析出验证码图片的URL是 captcha.php
$captcha_url = 'http://example.com/captcha.php';
// 初始化一个新的 cURL 资源
$ch_captcha = curl_init();
curl_setopt($ch_captcha, CURLOPT_URL, $captcha_url);
curl_setopt($ch_captcha, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch_captcha, CURLOPT_COOKIE, $cookie_string); // 关键:带上Cookie
// 执行请求
$captcha_image_data = curl_exec($ch_captcha);
// 将图片保存到本地,方便查看或交给识别服务
file_put_contents('captcha_code.jpg', $captcha_image_data);
echo "验证码图片已保存为 captcha_code.jpg\n";
curl_close($ch_captcha);

现在你的目录下会有一个 captcha_code.jpg 文件。

处理验证码(核心难点)

这是最复杂的一步,有三种主流策略:

策略A:手动输入(适用于个人或测试)

最简单的方法,将验证码图片显示出来,然后让用户手动输入。

// 显示图片 (在HTML中)
// <img src="captcha_code.jpg" alt="Captcha">
// 在命令行脚本中,可以提示用户输入
echo "请打开 captcha_code.jpg 图片,并输入验证码: ";
$captcha_code = trim(fgets(STDIN)); // 从命令行读取输入

优点:简单、免费、准确率高。 缺点:无法自动化,需要人工干预。

策略B:使用第三方打码平台(适用于商业或高频率采集)

这是最主流的自动化解决方案,你将验证码图片发送给专业的验证码识别服务,它们会返回识别结果。

国内有很多平台,如:

  • 云打码
  • 超级鹰
  • 打码兔

流程

  1. 注册平台账号,获取软件ID和密码。
  2. 将验证码图片(或图片的二进制数据)发送到平台的API。
  3. 平台返回识别出的字符串,并扣除你的余额。

伪代码示例(以超级鹰为例):

// 需要先下载超级鹰的SDK并引入
// require_once('Chaojiying.class.php');
// $chaojiying = new Chaojiying('你的用户名', '你的密码', '你的软件ID');
// // 读取验证码图片
// $captcha_image = file_get_contents('captcha_code.jpg');
// // 调用识别接口
// $result = $chaojiying->PostPic($captcha_image, 1001); // 1001是验证码类型代码
// if ($result['status'] == 0) {
//     $captcha_code = $result['pic_str']; // 识别成功
//     echo "识别结果: " . $captcha_code . "\n";
// } else {
//     echo "识别失败: " . $result['err_str'] . "\n";
// }

优点:高度自动化,识别率高(尤其对于复杂验证码)。 缺点:需要付费,有成本。

策略C:使用Tesseract OCR(适用于技术能力强、对成本敏感)

Tesseract是一个开源的OCR(光学字符识别)引擎,你可以将其安装到服务器上,然后通过PHP调用它来识别简单的验证码。

流程

  1. 安装Tesseract OCR。
    • Linux (Ubuntu/Debian): sudo apt-get install tesseract-ocr
    • Windows: 下载安装包并配置环境变量。
  2. 安装PHP的Tesseract扩展,如 tesseract-ocr/php-tesseract-ocr
  3. 使用扩展进行识别。

代码示例:

// 需要安装 tesseract-ocr/php-tesseract-ocr 扩展
require_once 'vendor/autoload.php';
use thiagoalessio\TesseractOCR\TesseractOCR;
try {
    // 对验证码图片进行预处理(可选但推荐)可以提高识别率
    // 灰度化、二值化、降噪等
    // 这里我们直接识别
    $captcha_code = (new TesseractOCR('captcha_code.jpg'))
        ->run();
    // 清理识别结果,去除空格和换行
    $captcha_code = preg_replace('/\s+/', '', $captcha_code);
    echo "OCR识别结果: " . $captcha_code . "\n";
} Exception (e) {
    echo "OCR识别失败: " . $e->getMessage() . "\n";
}

优点:免费,开源,可控。 缺点

  • 对复杂、扭曲、有干扰线的验证码识别率很低。
  • 需要自己搭建和维护环境。
  • 技术门槛较高。

提交登录表单

你已经有了所有登录所需的信息:$cookie_string, username, password, 和 $captcha_code

// 假设这些值已经准备好
$username = 'your_username';
$password = 'your_password';
// $captcha_code 从步骤三获取
// $cookie_string 从步骤一获取
// 登录请求的URL
$login_url = 'http://example.com/login.php';
// 初始化 cURL
$ch_login = curl_init();
// 构造POST数据
$post_data = [
    'username' => $username,
    'password' => $password,
    'captcha_code' => $captcha_code
];
curl_setopt($ch_login, CURLOPT_URL, $login_url);
curl_setopt($ch_login, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch_login, CURLOPT_POST, true); // 设置为POST请求
curl_setopt($ch_login, CURLOPT_POSTFIELDS, http_build_query($post_data)); // 设置POST数据
curl_setopt($ch_login, CURLOPT_COOKIE, $cookie_string); // 关键:带上之前的Cookie
// 执行登录请求
$login_response = curl_exec($ch_login);
// 检查登录是否成功
// 通常成功会返回 "登录成功" 或跳转,失败会返回 "验证码错误" 等
if (strpos($login_response, '登录成功') !== false || strpos($login_response, '欢迎') !== false) {
    echo "登录成功!\n";
    // 登录成功后,$ch_login 会话中已经包含了最新的有效Cookie
    // 你可以用这个 $ch_login 继续请求需要登录才能访问的页面
    $protected_page_url = 'http://example.com/user/profile.php';
    curl_setopt($ch_login, CURLOPT_URL, $protected_page_url);
    curl_setopt($ch_login, CURLOPT_POST, false); // 改为GET请求
    $profile_page = curl_exec($ch_login);
    echo "获取到的用户主页内容:\n" . $profile_page . "\n";
} else {
    echo "登录失败!\n";
    echo "服务器返回: " . $login_response . "\n";
}
// 关闭 cURL
curl_close($ch_login);

总结与最佳实践

  1. 会话管理是关键:整个过程都要小心处理Cookie。CURLOPT_COOKIE 是你的好朋友。
  2. 模拟浏览器:除了Cookie,还可以设置 User-Agent 等Header,让请求看起来更像来自真实浏览器。
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
  3. 错误处理:网络请求随时可能失败,务必加入 curl_errno()curl_error() 的判断。
  4. 选择合适的验证码解决方案
    • 个人/测试:手动输入。
    • 商业/高频:直接上第三方打码平台,省时省力。
    • 技术/低成本/简单验证码:可以尝试Tesseract OCR,但要对其效果有合理的预期。
  5. 尊重网站规则:采集数据时,请务必遵守目标网站的 robots.txt 协议和用户协议,不要对服务器造成过大压力,高频率的请求可能会被IP封禁。

通过以上步骤,你就可以用PHP攻克大多数带验证码的网站采集任务了。