访问网页时,每次都需要输入验证码,真的是太麻烦了
每次查询快递的时候,都需要进行验证,不是要输入验证码就是要滑块,那么有没有办法不用那么麻烦呢?当然是有的,要么是和快递公司进行接口对接,要么就是通过快递公司官网进行查询。
作为一个技术的爱好者,也作为一个顺丰快递粉丝,那么就以顺丰快递为例来进行一次技术的可行性研究吧。如果要进行技术对接,可以参考顺丰丰桥的接口即可。这里研究通过顺丰官网的方式来实现快递单号的自动查询。
首先我们要找到顺丰的官网。顺丰官网
在顺丰查询快递单号时,需要通过滑块的滑动来实现验证,那么实现自动查单号路由的难点就是要实现滑块的自动拖拽。
那么我们来整理一下思路和步骤:
顺丰的官方网址:顺丰官网
那么我们下面就开始进行实现的验证吧。
从个人喜欢用的工具和库来说,
①:我选择用DrissionPage来替代Selenium 来实现对应浏览器的访问和数据获取
②:模拟人工拖拉滑块的动作,使用PyAutoGUI来实现
③:使用Cv2来计算图片位置的计算
1、首先引入需要用到的模块:
import pyautogui
from time import sleep
from DrissionPage import ChromiumPage
import time
import requests
import cv2
pyautogui.PAUSE = 1 # 调用在执行动作后暂停的秒数,只能在执行一些pyautogui动作后才能使用,建议用time.sleep
2、使用浏览器访问目标网址
# 打开目标页面
def openBrowserPage():
page.get('https://www.sf-express.com/chn/sc')
sleep(1.5)
3、找到目标元素(输入框),输入要查询的快递单号,并点击查询
# 在目标页面的目标输入框中,自动填写单号并自动点击查询按钮
def set_postNo(postno):
input_area = page.ele('t:div@@class=bill-number')
input_area.ele('t:input@@type=text').input(postno)
sleep(0.3)
input_area.ele('t:button@@class=submit-button').click()
sleep(1)
4、计算缺口位置
# 计算缺口图片与背景图的距离并移动
def compute_move_postion():
# 等待页面加载完成,便于后续获取验证码(缺口)图片和背景图片
page.wait.load_start()
new_Iframe = page.ele('#tcaptcha_iframe')
target_Img = new_Iframe.ele('#slideBlock')
# print(f'目标图的坐标:{target_Img.location}')
# print(f'目标图的尺寸:{target_Img.size}')
# 下载缺口图片
DownLoadImg(target_Img.attr('src'), "start_pos.jpg")
target_Bg_Img = new_Iframe.ele('#slideBg')
# print(f'背景图的坐标:{target_Bg_Img.location}')
# print(f'背景图的尺寸:{target_Bg_Img.size}')
# 下载背景图片
DownLoadImg(target_Bg_Img.attr('src'), "end_pos.jpg")
# 计算(两个图片在网页中坐标起点)差值
chazhi = target_Img.location[0] - target_Bg_Img.location[0]
print(chazhi)
# data=computeDistance()
# data=distance()
data = identify_gap(r'start_pos.jpg', r'end_pos.jpg')
print(data)
# moveVal = data[0] - chazhi * 2
# print(moveVal + 30)
#
# dealVerify(moveVal + 30)
moveVal = data[0] - chazhi
print(moveVal)
dealVerify(moveVal)
部分代码解释:
new_Iframe = page.ele('#tcaptcha_iframe') target_Img = new_Iframe.ele('#slideBlock') 找到滑块缺口图片和背景图片元素,便于将图片下载到本地
# 计算(两个图片在网页中坐标起点)差值
chazhi = target_Img.location[0] - target_Bg_Img.location[0]
5、计算缺口值
# 计算缺口坐标
def identify_gap(bg, cut):
'''
bg: 背景图片
cut: 缺口图片
'''
# 读取背景图片和缺口图片
bg_img = cv2.imread(bg) # 背景图片
cut_img = cv2.imread(cut) # 缺口图片
# 识别图片边缘
bg_edge = cv2.Canny(bg_img, 100, 200)
cut_edge = cv2.Canny(cut_img, 100, 200)
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
cut_pic = cv2.cvtColor(cut_edge, cv2.COLOR_GRAY2RGB)
# 缺口匹配
res = cv2.matchTemplate(bg_pic, cut_pic, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配
# 返回缺口坐标
return max_loc
6、使用PyAutoGUI移动滑块
# 移动滑块
def dealVerify(move):
drag_btn = pyautogui.locateOnScreen(r'./sf_img/start_postion.png', confidence=0.6, grayscale=True)
if drag_btn is not None:
pyautogui.moveTo(drag_btn, duration=1)
pyautogui.dragRel(move, 0, duration=1, button='left')
else:
print('未识别到图标')
7、图片下载方法:
# 将网络图片下载到本地
def DownLoadImg(img_link, path):
data = requests.get(img_link).content
while True:
time.sleep(0.2)
if len(data) > 5:
break
with open(path, "wb") as f:
f.write(data)
8、方法整体调用:
if __name__ == "__main__":
# Win+D 返回桌面
pyautogui.hotkey('winleft', 'd')
# 打开谷歌浏览器
page = ChromiumPage()
# 在谷歌浏览器中打开目标网址
openBrowserPage()
postno = '要查询的快递单号XXXXXXXXXXXXXXXXXXXX'
# 自动填写快递单号并检索
set_postNo(postno)
compute_move_postion()
通过上面的步骤,可以实现顺丰快递单号的自动查询,通过如果需要查询后的结果,可以使用DrissionPage 来获取查询的结果。
写在最后
上述的方法可以实现通过模拟人工的形式快递单号的自动查询,当然,仅仅用作技术研究。