You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel API爬取数据遇验证码拦截问题求助及方案咨询

Laravel API 验证码拦截问题解决方案

问题背景

你的Laravel API爬取某站点时被验证码拦截返回空结果,此前通过Python的Selenium+BeautifulSoup结合「验证码转音频再转文本」的逻辑可正常爬取该站点数据,当前需针对Laravel场景落地可行方案。


思路1:Laravel直接整合Python验证码处理脚本

利用已有的Python验证码解析逻辑,让Laravel通过进程调用执行脚本,快速复用现有能力。

实现步骤

  1. 将Python验证码处理脚本(如captcha_solver.py)放置在Laravel项目的storage/app/scripts目录,确保服务器安装Python及脚本依赖库(如SpeechRecognition、pydub)。
  2. 在Laravel Service中,通过Laravel内置的Process组件调用脚本,传递验证码音频文件/URL,获取解析后的文本。
  3. 携带验证码文本重新构造请求,完成数据爬取。

代码示例(Laravel Service)

<?php

namespace App\Services;

use Illuminate\Support\Facades\Process;
use Symfony\Component\DomCrawler\Crawler;

class CrawlerService
{
    public function crawlTargetSite()
    {
        // 1. 发起初始请求,获取验证码音频链接与Cookie
        $initialResponse = \Illuminate\Support\Facades\Http::get('https://target-site.com');
        $captchaAudioUrl = $this->extractCaptchaAudioUrl($initialResponse->body());
        $cookies = $initialResponse->cookies();

        // 2. 调用Python脚本解析验证码
        $captchaText = $this->solveCaptcha($captchaAudioUrl);

        // 3. 提交带验证码的请求
        $finalResponse = \Illuminate\Support\Facades\Http::withCookies($cookies, 'target-site.com')
            ->post('https://target-site.com/verify', [
                'captcha' => $captchaText,
                // 其他必要请求参数
            ]);

        return $finalResponse->json();
    }

    private function solveCaptcha(string $audioUrl): string
    {
        // 下载验证码音频到临时目录
        $tempAudioPath = storage_path('app/temp/captcha.mp3');
        file_put_contents($tempAudioPath, file_get_contents($audioUrl));

        // 调用Python脚本处理音频转文本
        $processResult = Process::run(sprintf(
            'python %s %s',
            storage_path('app/scripts/captcha_solver.py'),
            escapeshellarg($tempAudioPath)
        ));

        // 清理临时文件
        unlink($tempAudioPath);

        return trim($processResult->output());
    }

    private function extractCaptchaAudioUrl(string $html): string
    {
        $crawler = new Crawler($html);
        return $crawler->filter('audio#captcha')->attr('src');
    }
}

思路2:搭建独立Python服务,Laravel通过API调用

将验证码解析逻辑封装为独立Python服务,Laravel通过HTTP请求调用,实现技术栈解耦,便于复用和维护。

实现步骤

  1. 用FastAPI/Flask搭建Python服务,暴露/solve-captcha接口,接收验证码音频文件或URL,返回解析后的文本。
  2. Laravel通过HTTP请求调用该服务,获取验证码结果后继续爬取流程。

Python服务示例(FastAPI)

from fastapi import FastAPI, UploadFile, File
import speech_recognition as sr
from pydub import AudioSegment
import os

app = FastAPI()

@app.post("/solve-captcha")
async def solve_captcha(audio: UploadFile = File(...)):
    # 保存上传的音频文件
    temp_mp3 = "temp_captcha.mp3"
    with open(temp_mp3, "wb") as f:
        f.write(await audio.read())

    # 转换音频格式为wav(适配识别库)
    sound = AudioSegment.from_mp3(temp_mp3)
    temp_wav = "temp_captcha.wav"
    sound.export(temp_wav, format="wav")

    # 音频转文本
    recognizer = sr.Recognizer()
    with sr.AudioFile(temp_wav) as source:
        audio_data = recognizer.record(source)
        captcha_text = recognizer.recognize_google(audio_data)

    # 清理临时文件
    os.remove(temp_mp3)
    os.remove(temp_wav)

    return {"captcha_text": captcha_text}

Laravel调用示例

private function solveCaptchaViaService(string $audioUrl): string
{
    $audioContent = file_get_contents($audioUrl);
    $response = \Illuminate\Support\Facades\Http::attach(
        'audio', $audioContent, 'captcha.mp3'
    )->post('http://your-python-service:8000/solve-captcha');

    return $response->json()['captcha_text'];
}

思路3:Laravel直接绕过验证码(优化方案)

放弃修改Cookie的不稳定方式,采用更可靠的无头浏览器模拟或第三方服务方案。

方案A:无头浏览器模拟真实用户行为

使用spatie/browsershot集成Puppeteer,模拟Selenium的真实浏览器行为,自动处理验证码流程。

代码示例

use Spatie\Browsershot\Browsershot;

public function crawlWithHeadlessBrowser()
{
    $resultHtml = Browsershot::url('https://target-site.com')
        ->waitForSelector('audio#captcha')
        ->evaluate('async () => {
            // 获取验证码音频链接并调用Laravel内部解析接口
            const audioUrl = document.querySelector("audio#captcha").src;
            const captchaRes = await fetch(`/api/internal/solve-captcha?url=${audioUrl}`);
            const captchaData = await captchaRes.json();
            
            // 填写验证码并提交表单
            document.querySelector("input[name=captcha]").value = captchaData.text;
            document.querySelector("form#verify-form").submit();
            
            // 等待页面加载完成后返回HTML
            await new Promise(resolve => setTimeout(resolve, 2000));
            return document.body.innerHTML;
        }')
        ->bodyHtml();

    // 解析返回的HTML数据
    $crawler = new Crawler($resultHtml);
    return $crawler->filter('.target-data-container')->extract(['text']);
}

方案B:接入第三方验证码识别服务

若自研解析逻辑稳定性不足,可直接调用百度OCR、腾讯云验证码识别等第三方API,在Laravel中直接完成验证码解析,无需依赖Python环境。


方案选择建议

  • 若已有成熟Python解析逻辑,思路1是最快落地的方案,适合小流量场景。
  • 若需复用解析逻辑或服务器环境限制PHP与Python共存,思路2架构更清晰,便于扩展。
  • 若希望完全基于PHP生态解决,思路3的方案A模拟真实用户行为,成功率更高。

内容的提问来源于stack exchange,提问作者testttt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 05:01:13