Python网络爬虫实现发送短信验证码的方法
本文详细讲解如何利用Python网络爬虫技术实现自动发送短信验证码。通过Chrome开发者工具抓取目标网站接口,分析URL中的时间戳参数构造动态请求,获取验证码图片。结合超级鹰接口进行OCR图像识别,最终通过POST请求提交手机号与识别结果,完成短信发送流程。
Python爬虫发送短信验证码实战
前言:本文将总结如何通过程序实现短信发送功能。这通常涉及调用特定的API接口,下文将对此进行详细介绍。这些内容均为个人实践总结,旨在通过持续输出博客来巩固知识。接下来直接进入正题。
网络爬虫实现发送短信验证码
在实现具体功能前,必须建立清晰的思路,否则代码开发将失去方向。
要实现短信发送,首先需要进行分析。我们可以选择一个支持发送短信的网站页面作为分析对象。
访问该页面后,界面如下所示:

这是一个注册界面,注册时要求填写手机号码,通常还包含验证码识别环节。如果初始界面未显示验证码,可以尝试输入几个号码并多次点击发送,刷新几次后即可看到验证码界面。
为了避免给他人造成麻烦,这里使用自己的号码进行测试。 多次刷新界面会出现验证码,但需填写不同的手机号码。我们的目标是看到带有验证码的界面。

网络抓包与接口分析
接下来打开Chrome浏览器的开发者工具(即网络检查工具)。点击Network标签进行抓包,建议在抓包前清除已有的数据包列表。然后点击验证码按钮,使网页产生响应,同步观察并抓取数据包。

当填写手机号后,点击验证码按钮进行抓包,结果如下所示:

可以看到,点击同步瞬间仅有一个相关的数据包。在执行其他操作时可能会出现其他数据包,但与本次目标无关。
直接点击该数据包查看详情。

重点观察其中的URL地址。
https://uc.creditcard.ecitic.com/citiccard/ucweb/newvalicode.do?time=1613969346256
打开该URL查看其实际返回内容。
注意观察time参数,这显然是一个时间戳参数。
这里有必要介绍一下时间戳的概念。
时间戳是指从格林威治时间1970年1月1日0点0分0秒开始计算的秒数。 秒级时间戳:10位数字 毫秒级时间戳:13位数字 微秒级时间戳:16位数字
可以看出,这里的time参数属于毫秒级时间戳。
每次访问该页面并刷新,都会获得不同的验证码,并返回当前时间。若要获取当前验证码,需要构造包含time参数的URL。其他参数保持不变,只需获取当前的time值。那么如何获取这个time值呢?
时间戳参数构造与动态URL生成
Python中提供了time库,下面展示如何使用它。
下面展示一些 内联代码片。
import time
def get_time() :
" 获取当前的时间戳"
now_time =str(int(time.time()*1000))#获取毫秒级的时间戳
print('当前的时间戳',now_time)
return now_time
get_time()
查看运行结果。
我们可以按以下方式操作。

将获取到的时间戳参数加入URL中,即可实现动态获取。每次获取二维码时需指定当前的time参数,因此可以这样构造URL:使用一个变量接收时间戳,并以字符串形式拼接到time参数后。
下面展示一些 内联代码片。
import time
def get_time() :
" 获取当前的时间戳"
now_time =str(int(time.time()*1000))#获取毫秒级的时间戳
print('当前的时间戳',now_time)
return now_time
time_one = get_time()
img_url = 'https://uc.creditcard.ecitic.com/citiccard/ucweb/newvalicode.do?time='+time_one
print(img_url)
检查是否可以获取到正确的URL。

点击那个蓝色链接,查看是否成功获取到验证码图片。
测试证明我们的方法是正确的。
下一步是实现代码访问,获取并保存该验证码。保存的原因在于我们需要后续处理。

观察这三个提交栏,显然这是一个表单提交过程。提交数据需要使用POST请求,POST请求用于提交手机号码和图形验证码数据。
当数据提交成功后,手机会收到短信验证码。以此方式即可实现发送短信验证码的功能。
验证码图片获取与保存
接下来保存图片验证码。
下面展示一些 内联代码片。
import time
import requests
def get_time() :
" 获取当前的时间戳"
now_time =str(int(time.time()*1000))#获取毫秒级的时间戳
print('当前的时间戳',now_time)
return now_time
time_one = get_time()
img_url = 'https://uc.creditcard.ecitic.com/citiccard/ucweb/newvalicode.do?time='+time_one
print(img_url)
headers = {
'User-Agent' :'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36'
}
response = requests.get(url=img_url,headers = headers)
img_data = response.content
with open('yzm.jpg',mode = 'wb') as file :
file.write(img_data)

可以看到代码编辑器右侧已出现保存的图片文件。
下一步继续分析手机号码和图片验证码数据是如何传入的,以及具体实现方式。
输入手机号码和图片验证码后,点击“免费获取”。此时再次进行抓包,方法与前文第一次抓包相同。
观察会出现什么样的数据包。

蓝色部分即为我们寻找的目标包。接下来如何操作?点击打开查看相应的代码。

可以看到这是一个POST请求,用于提交表单数据。查看下方的表单数据。
这里会发现一个不同点:电话号码是直接的数字,而图片验证码需要处理。因为前文保存的验证码是图片,如何识别出图片中的数据进行传入?这里还需要借助一个网站。
超级鹰OCR接口集成与代码修正
超级鹰用于识别验证码,实际上也是调用其接口。

点击开发文档,由于我们使用Python编写代码,因此点击Python图标,查看所需内容。

在下方找到超级鹰图像识别模块,然后点击下载。将解压后的API接口py文件导入到Python编辑器中。这里使用PyCharm,直接将解压出的Python文件拖入PyCharm即可。

下面是其中的部分代码。

这里做了少量修改。直接来看这段代码的内容。 我要告诉大家,原始代码存在低级错误。
#!/usr/bin/env python
# coding:utf-8
import requests
from hashlib import md5
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001') #用户中心>>软件ID 生成一个替换 96001
im = open('a.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print chaojiying.PostPic(im, 1902) #1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
上面是其原始接口代码,这很不合理。分块来分析。
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')#没有缩进
self.password = md5(password).hexdigest()
self.soft_id = soft_id
.......
.......
错误在哪里?这里特意标出,原始代码直接复制粘贴并不显眼,但用编辑器打开会有问题。
if __name__ == '__main__':
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001') #用户中心>>软件ID 生成一个替换 96001
im = open('a.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print chaojiying.PostPic(im, 1902) #print没有加 () #1902 验证码类型 官方网站>>价格体系 3.#4+版 print 后要加()
还有一处问题在这里,代码格式也未写对,这里指出,读者应该能发现。建议读者去平台下载该接口,自行修改。
好,不再谈论这些,我们继续。我们仍需修改部分代码。
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001') #用户中心>>软件ID 生成一个替换 96001
im = open('a.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print chaojiying.PostPic(im, 1902) #这是原始的代码 #1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
可以在内部编写一个方法,稍后调用该代码接口时直接调用此方法。
注意在类中添加这样一部分代码,即编写一个方法。
def run(self):
chaojiying = Chaojiying_Client(constant.USER_NAME, constant.PASSWORD,
913137) # 用户中心>>软件ID 生成一个替换 96001
im = open('yzm.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
result = chaojiying.PostPic(im, 1004) # 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
return result['pic_str']
注意分析该接口代码,其中 chaojiying = Chaojiying_Client(constant.USER_NAME, constant.PASSWORD,913137)。
注释中已说明得很清楚,这里的constant代表我们要导入的py文件,其中包含用户名、密码以及软件ID。
im = open(‘yzm.jpg', ‘rb').read() 打开你保存的验证码文件,上面我们已经保存过。
result = chaojiying.PostPic(im, 1004) 1004代表你的验证码类型。
用户名和密码需要注册。那么软件ID和验证码类型如何确定? 这是主页,请点击价格体系。

在下方你可以判断你的验证码类型。

我们需要登录进入用户中心。

进入如下界面。

往下拉进入软件ID部分。

进入后点击生成一个软件ID,软件名称和软件说明可以随意填写。

这样我们就可以获得一个软件ID。
这个constant如何编写很简单,建立一个py文件,里面写入。
USER_NAME=' …'
PASSWORD='… '
然后保存即可。将py文件导入到当前路径,然后import即可。
完整代码实现与短信发送结果
现在我们来看完整的代码。 接口完整修改后的代码。
import requests
from hashlib import md5
import constant
import constant
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
self.password = md5(password.encode('utf8')).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
def run(self):
chaojiying = Chaojiying_Client(constant.USER_NAME, constant.PASSWORD,
913137) # 用户中心>>软件ID 生成一个替换 96001
im = open('yzm.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
result = chaojiying.PostPic(im, 1004) # 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
return result['pic_str']
if __name__ == '__main__':
chaojiying = Chaojiying_Client(constant.USER_NAME, constant.PASSWORD, 913137) # 用户中心>>软件ID 生成一个替换 96001
im = open('yzm.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
result = chaojiying.PostPic(im, 1004)
print(chaojiying.PostPic(im,1004))# 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
主文件代码,从这里执行。
import time
import requests
from chaojiying import Chaojiying_Client
import constant
def get_time() :
" 获取当前的时间戳"
now_time =str(int(time.time()*1000))#获取毫秒级的时间戳
print('当前的时间戳',now_time)
return now_time
time_one = get_time()
img_url = 'https://uc.creditcard.ecitic.com/citiccard/ucweb/newvalicode.do?time='+time_one
print(img_url)
headers = {
'User-Agent' :'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36'
}
response = requests.get(url=img_url,headers = headers)
img_data = response.content
with open('yzm.jpg',mode = 'wb') as file :
file.write(img_data)
print(response)
#验证码识别
code = Chaojiying_Client(constant.USER_NAME,constant.PASSWORD,913137).run()
print('识别出来的验证码为',code)
#请求保证同一个用户
cookiejar = response.cookies
cookies = cookiejar.get_dict()
print(cookies)
data = {
'phone' :19745678397,
'imgValidCode' : code,
}
time_two = get_time()
code_url = 'https://uc.creditcard.ecitic.com/citiccard/ucweb/getsms.do?×tamp'+time_two
requests_two = requests.post(url=code_url,data= data,headers=headers,cookies=cookies)
print(requests_two.json())
查看运行结果。

OK,短信发送成功。 需要注意的是,如果发送多次,会出现短信发送频率过高的提示,这是服务器的响应。
总结该程序实现了发送验证码的功能。如果需要发送你想要的文本,需要调用其他接口。其他不多说了,毕竟爬虫也需要讲武德。
到此这篇关于python网络爬虫实现发送短信验证码的方法的文章就介绍到这了,更多相关python爬虫发送短信验证码内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













