Laravel API爬取数据遇验证码拦截问题求助及方案咨询
Laravel API 验证码拦截问题解决方案
问题背景
你的Laravel API爬取某站点时被验证码拦截返回空结果,此前通过Python的Selenium+BeautifulSoup结合「验证码转音频再转文本」的逻辑可正常爬取该站点数据,当前需针对Laravel场景落地可行方案。
思路1:Laravel直接整合Python验证码处理脚本
利用已有的Python验证码解析逻辑,让Laravel通过进程调用执行脚本,快速复用现有能力。
实现步骤
- 将Python验证码处理脚本(如
captcha_solver.py)放置在Laravel项目的storage/app/scripts目录,确保服务器安装Python及脚本依赖库(如SpeechRecognition、pydub)。 - 在Laravel Service中,通过Laravel内置的
Process组件调用脚本,传递验证码音频文件/URL,获取解析后的文本。 - 携带验证码文本重新构造请求,完成数据爬取。
代码示例(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请求调用,实现技术栈解耦,便于复用和维护。
实现步骤
- 用FastAPI/Flask搭建Python服务,暴露
/solve-captcha接口,接收验证码音频文件或URL,返回解析后的文本。 - 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
相关产品推荐
相关产品推荐

