import time
from urllib.request import urlretrieve
import random
import cv2
import numpy as np
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
import time
import datetime
class CrackSlider:
"""
通过浏览器截图,识别验证码中缺口位置,获取需要滑动距离,并模仿人类行为破解滑动验证码
"""
def __init__(self, browser, url):
super(CrackSlider, self).__init__()
# 实际地址
self.url = url
self.driver = browser
self.wait = WebDriverWait(self.driver, 20)
self.zoom = 0.7722
# zoom=0.7722 图片实际大小为360psi,但是界面中大小为278,故zoom=278/360
def open(self):
self.driver.get(self.url)
def get_pic(self):
time.sleep(1)
target = browser.find_element_by_class_name("JDJRV-bigimg").find_element_by_xpath('img').get_attribute('src')
template = browser.find_element_by_class_name("JDJRV-smallimg").find_element_by_xpath('img').get_attribute(
'src')
small_image_name = 'template.png' # 背景大图名
big_image_name = 'target.jpg' # 滑块图片名
urlretrieve(target, big_image_name)
urlretrieve(template, small_image_name)
def get_tracks(self, distance):
"""
根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹
"""
# 移动轨迹
track = []
# 当前位移
current = 0
# 减速阈值
mid = distance * 3 / 5
# 计算间隔
t = 0.2
# 初速度
v = 0
while current < distance:
if current < mid:
# 加速度为正2
a = 4
else:
# 加速度为负3
a = -2
# 初速度v0
v0 = v
# 当前速度v = v0 + at
v = v0 + a * t
# 移动距离x = v0t + 1/2 * a * t^2
move = v0 * t + 0.5 * a * t * t
# 当前位移
current += move
# 加入轨迹
track.append(round(move))
sum_forward = sum(track)
if abs(sum_forward-distance) < 0.01:
back_tracks = [0, 0, 0, 0]
else:
back_tracks = [0,0,distance-sum_forward]
return {'forward_tracks': track, 'back_tracks': back_tracks}
def openCVmatch(self, target, template):
"""
使用openCV来完成 找到图片的缺口
:param target:
:param template:
:return:
"""
img_rgb = cv2.imread(target)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread(template, 0)
gray_mean = np.mean(template)
# 根据平均灰度二值化模型
ret, img_threshed = cv2.threshold(img_gray, gray_mean, 255, cv2.THRESH_BINARY)
# 图片灰度显示
# cv2.namedWindow('GRAY', cv2.WINDOW_AUTOSIZE)
# cv2.imshow("GRAY", img_threshed)
# cv2.waitKey(0)
ret, template_threshed = cv2.threshold(template, gray_mean - 20, 255, cv2.THRESH_BINARY_INV)
run = 1
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_threshed, template_threshed, cv2.TM_CCOEFF_NORMED)
# 图片灰度显示
# cv2.namedWindow('GRAY', cv2.WINDOW_AUTOSIZE)
# cv2.imshow("GRAY",template_threshed)
# cv2.waitKey(0)
min_val, max_val, min_indx, max_indx = cv2.minMaxLoc(res)
print("max_indx = {0}".format(max_indx[0]))
# cv2.rectangle(img_threshed, (max_indx[0], max_indx[1]), (max_indx[0] + 50, max_indx[1] + 50), (0, 0, 255))
# cv2.imshow("GRAY", img_threshed)
# cv2.waitKey(0)
print("应向前距离:{0}".format(max_indx[0] * self.zoom))
return max_indx[0]
def crack_slider(self, browser):
# self.open()
target = 'target.jpg'
template = 'template.png'
self.get_pic()
distance = self.openCVmatch(target, template)
tracks = self.get_tracks(distance * self.zoom) # 对位移的缩放计算
slider = browser.find_element_by_class_name('JDJRV-slide-btn')
ActionChains(browser).click_and_hold(slider).perform()
print("向前距离:{0}".format(sum(tracks['forward_tracks'])))
for track in tracks['forward_tracks']:
ActionChains(browser).move_by_offset(xoffset=track, yoffset=0).perform()
time.sleep(0.01)
time.sleep(0.5)
print("向后距离:{0}".format(sum(tracks['back_tracks'])))
for back_tracks in tracks['back_tracks']:
ActionChains(browser).move_by_offset(xoffset=back_tracks, yoffset=0).perform()
# ActionChains(browser).move_by_offset(xoffset=-3, yoffset=0).perform()
# ActionChains(browser).move_by_offset(xoffset=3, yoffset=0).perform()
time.sleep(0.3)
ActionChains(browser).release().perform()
time.sleep(1)
try:
elem = browser.find_element_by_class_name("JDJRV-slide-center")
print("验证未通过")
success = False
time.sleep(random.randint(1, 5))
except:
print('验证成功')
time.sleep(1)
return None
if success is False:
success = True
self.crack_slider(browser)
class JDCoupon:
def get_coupon(self, driver, quan_link):
# self.driver.find_element_by_class_name(quan_link).click()
driver.get(quan_link)
time.sleep(3)
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
print('successful!!!')
if __name__ == '__main__':
username = "your login name" # 填自己的用户名
passwd = "your passord" # 填用户名对应的密码
browser = webdriver.Chrome()
# browser = webdriver.Ie()
url = "https://sale.jd.com/act/ZgSB2AKYjosIdc05.html?cpdad=1DLSUE&cu=true&utm_source=kong&utm_medium=jingfen&utm_campaign=t_2011222265_&utm_term=9d44332eccb9469987f699015a54dfff"
browser.get(url)
browser.implicitly_wait(5)
browser.find_element_by_link_text('你好,请登录').click()
browser.implicitly_wait(2)
browser.find_element_by_link_text('账户登录').click()
# 需要自己按F12查原网址对应的用户名和密码框的id_name
elem = browser.find_element_by_id("loginname")
elem.send_keys(username)
elem = browser.find_element_by_id("nloginpwd")
elem.send_keys(passwd)
time.sleep(3)
elem = browser.find_element_by_id("loginsubmit")
elem.click()
browser.implicitly_wait(10)
browser.switch_to.window(browser.window_handles[-1])
c = CrackSlider(browser, url)
try:
elem = browser.find_element_by_class_name("JDJRV-slide-center")
print(elem.text)
print('-----需要验证-----')
c.crack_slider(browser)
except:
print('-----无需要验证码验证-----')
jd = JDCoupon()
jd.get_coupon(browser,
"https://act-jshop.jd.com/couponSend.html?callback=jQuery6834021&ruleId=16871691&key=423a7ac54d014e61a865019a38ddca4c&eid=KJY6T2OMF4FUFUNDJNUJA3JQ2BNJPFMM5O4O65DPRGOFSYV2VZ7WYKWGVTMBTZDBJFGOGZJ67RKGK4R3RTSG56QILU&fp=59cb76e48ac60c9046d017ca6640a478&shshshfp=8b913e849574b8ca396b9f005b642803&shshshfpa=7f75e3f1-42f8-2e23-f9a9-d5152d4c798c-1546855473&shshshfpb=s4evJAXMQiCf8S78NC3xTaw%253D%253D&jda=122270672.154685547268065187417.1546855473.1546855473.1546855473.1&pageClickKey=pageclick%7Ckeycount%7Ccoupon_simple_39991210_2%7C0&platform=0&applicationId=1693270&_=1546855602370")
"""
---------------------
作者:jingj