Python中如何实现验证码URL与请求的同步处理?

This is an example link

这是获取验证码连接

没有任何参数,怎么确保每次的查询,才能对应上这个验证码呢?


Python中如何实现验证码URL与请求的同步处理?
29 回复

在Python里处理验证码URL和请求同步,核心就是保持会话(session)和正确处理时间。直接用requests.Session()来管理cookies,确保验证码图片的请求和提交表单的请求在同一个会话里。关键点在于拿到验证码URL后,立刻用同一个session去下载图片,然后马上提交表单,别拖太久,有些验证码会话过期很快。

下面是个典型场景的代码示例,模拟登录一个需要验证码的网站:

import requests
from PIL import Image
from io import BytesIO
import time

# 1. 创建会话对象,保持所有请求的cookies
session = requests.Session()

# 2. 首次访问登录页,获取必要的初始cookies(如果需要)
login_page_url = "https://example.com/login"
session.get(login_page_url)

# 3. 获取验证码图片
# 假设验证码URL是固定的,或者从登录页响应中解析出来
captcha_url = "https://example.com/captcha.jpg"

# 关键:用同一个session获取验证码图片
captcha_response = session.get(captcha_url)

# 4. 展示或识别验证码(这里展示,实际可能需要OCR)
img = Image.open(BytesIO(captcha_response.content))
img.show()  # 弹出图片查看
# 如果是自动识别,这里调用你的OCR函数
# captcha_code = your_ocr_function(captcha_response.content)

# 5. 手动输入看到的验证码
captcha_code = input("请输入验证码: ")

# 6. 立即构造登录数据并提交
login_data = {
    'username': 'your_username',
    'password': 'your_password',
    'captcha': captcha_code  # 验证码字段名根据实际网站定
}

# 关键:用同一个session提交登录请求
login_response = session.post(
    "https://example.com/login",
    data=login_data
)

# 7. 检查登录是否成功
if "登录成功" in login_response.text:
    print("登录成功!")
    # 之后可以用这个session继续访问需要登录的页面
else:
    print("登录失败,可能是验证码错误或过期")

要点:

  • 必须用requests.Session():它自动处理cookies,让验证码请求和登录请求关联。
  • 速度要快:获取验证码后尽快提交,避免会话过期。如果网站验证码绑定时间戳,你可能需要更精确的同步。
  • 注意反爬:有些网站会在验证码请求里加动态参数,你需要从登录页HTML里提取真实的验证码URL。

如果验证码URL是动态生成的(比如带timestamptoken参数),你需要先解析登录页HTML,用正则或BeautifulSoup提取出真正的URL,再用session去请求那个动态URL。

总结:用Session保持状态,拿到验证码后尽快提交。


我处理过的是,同一 session 去访问 example link,然后再去访问验证码,这就就等于刷新了验证码

通常的做法是 session 保存。

requests.Session().get(“http://www.cszjw.net/newCaptcha”)获取的验证码,始终与 example link 不同步,不知道为什么

说 session 存储的,如果是集群部署,同时没有 ip 固定的策略怎么处理?

响应头:Set-Cookie

把验证码放 Cookie 中,你认真的吗?

http://www.cszjw.net/newCaptcha?r=0.37396028425505023
====
这个不是参数?
===
用 session 方式感觉真古老

要同一个 session 啊

不好意思,我脑子短路了,集群下的 session 也可以集中存储。

集中储存就会成为瓶颈哦

明明带了一个参数



那怎么同步这个验证码呢

你是要用网页的形式代替 api 么?是的话 记录号 cookie 就行了,服务端根据 cookie 就会认为你是同一个人,同一个人的验证码会覆盖的,永远是最后获取的那个

可以再弄个 sessions 的集群啊,只是 sessions 的出入口唯一就行了。

理论依据:HTTP 单次访问是无状态的,但 HTTP 连续访问是有会话状态的;会话状态由服务器保存;只要能够保证获取验证码、使用验证码这两个请求处于同一个会话,那么验证码就是可以验证的。

HTTP 会话状态是 OSI 第七层应用层独立管理的事,跟第四层传输层 TCP 连接没有任何关系。

HTTP 会话跟踪原理:首次连接服务器生成唯一标识,并且通知客户端;后续连接,客户端都带上该标识;服务器根据唯一标识,判断是否属于同一个会话。唯一标识由服务器生成和校验,客户端只能够暂存和传递,所以该会话是完全由服务器控制的。

HTTP 会话 Cookie 实现方式:服务器通过 set-cookie 将唯一标识通知给客户端,一般都会制定 cookie 的有效期是内存级别,级浏览器关了 cookie 就没了。

HTTP 会话 URL 重写实现方式:服务器通过 URL 重定向将唯一标识通知给客户端,唯一标识就在新的 URL 地址上,客户端不保存唯一标识,但后续的所有请求的 URL 地址中,都回带上唯一标识。此方式很容易失效。

以上两种,只是传统的实现方式,并不是唯一的。你完全可以抛开浏览器和服务器框架,自己实现会话跟踪。例如:如果服务器愿意,浏览器可以通过 H5 的 web 存储暂存唯一标识;服务器也可以抛开语言框架,自己写业务代码,用 redis 或者独立服务管理唯一标识(此时集群就不是事了)。甚至,经服务器允许后,多个客户端通过共享唯一标识,也可以共享会话;当然会话管理服务器、验证码服务器、业务服务器也可以是不同的服务器。

我是说响应回来的新 cookies 里面可以对应上

可以加密…= =

搞不定球,日了狗🐶

cookies 存的只是验证码的序号,key 呀,验证的是 value


1. 创建 session 对象
2. 请求一次查询页面
3. 请求验证码页面,识别出验证码
4. post 请求

每次请求验证码相当于刷新验证码,别重复请求!

围观楼上诸位大佬扯淡 (doge,极其普通的验证码也能扯上这么多 (滑稽

你下载完了之后要保证后面访问页面的时候不会再次请求验证码这个地址,访问页面时候把验证码图片请求拦截干掉,验证码就不会变动了。。跟 session 什么的鬼东西一毛钱关系都没有,那是后端的玩意,跟请求跟页面有一毛钱关系,亏楼上还讨论的这么津津有味


或者你换一个方法,不要下载验证码,先访问页面,把验证码区域截个图然后获得验证码图片,还更简单粗暴可靠叼炸天

你只要明白一点,每一次请求验证码,cookies 都会更新一次回来,你只要输入最后一次请求看到的验证码以及提交正确的 cookies 就行。

验证码可以放 cookie。只要保证 用户自己还原不出来、而服务端可以还原出来 就行了。discuz 里有个函数叫 authcode(),就能解决这个问题。

session 在客户端的表现,其实是 cookie 里存了一个 id,所以你只需要带上 cookie 信息就会被服务器识别成同一个回话

简单,约定下 key,存 redis

session 可以用 cookie 存呀,加密就行了。Rails 默认就这么搞的

session_id 了解下
下载验证码时要同时保存 cookie,下次提交时要提交保存的 cookie

我就是这种操作,仍不行啊
下载验证码到本地并获取 cookies
r = requests.get(“获取验证码连接”)
urllib.request.urlretrieve(r.url, “./a.jpg”)
self.cookies = dict(r.cookies)
==========================
查询时,添加下载验证码的 cookies
r = requests.Session().post(“查询链接”,data=self.data, cookies=self.cookies)
print(self.data)
r.encoding = “utf-8”
print(r.text)

回到顶部