如何破解類似於簡書登入的滑動式驗證碼

簡書簡書,時隔半年我又來搞事了,之前有在未登入模式下,爬取過簡書的專題和 首頁推薦文章,而現在在參考網上大神的程式碼搞過微博、知乎模擬登入後,感覺自己也是棒棒噠,於是開搞簡書!一開始也以為最多就是一個驗證碼的圖片咯,畢竟簡書這麼友好是吧~結果!excuse me??這裡寫圖片描述

好吧,當時我就懵比了,簡書你變了!你怎麼不按照套路出牌?!

這裡寫圖片描述

但是,本人是不會輕易嚥氣的,科科,小樣,我還能百度呢。調出firebug
檢視介面元素,發現此滑動驗證碼的程式碼如下,geetest是個什麼東東,看起來很可疑啊,然後百度了下,喲呵,令惡意程式敬畏、使用者喜愛的驗證安全體系啊~然後,知道了出處,繼續一搜,破解途徑出現——http://blog.csdn.net/paololiu/article/details/52514504 ,前人栽樹,後人乘涼。後面就是我略略修改了一下大神的程式碼,然後就ok啦。

這裡寫圖片描述

貼上程式碼:


#!/usr/bin/env python
# -*- coding:utf-8 -*-
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.support.wait import WebDriverWait
import PIL.Image as image
import time,re,cStringIO,urllib2,random
def get_merge_image(filename,location_list):
'''
根據位置對圖片進行合併還原
:filename:圖片
:location_list:圖片位置
'''
pass
im = image.open(filename)
new_im = image.new('RGB', (260,116))
im_list_upper=[]
im_list_down=[]
for location in location_list:
if location['y']==-58:
pass
im_list_upper.append(im.crop((abs(location['x']),58,abs(location['x']) 10,166)))
if location['y']==0:
pass
im_list_down.append(im.crop((abs(location['x']),0,abs(location['x']) 10,58)))
new_im = image.new('RGB', (260,116))
x_offset = 0
for im in im_list_upper:
new_im.paste(im, (x_offset,0))
x_offset  = im.size[0]
x_offset = 0
for im in im_list_down:
new_im.paste(im, (x_offset,58))
x_offset  = im.size[0]
return new_im
def get_image(driver,div):
'''
下載並還原圖片
:driver:webdriver
:div:圖片的div
'''
pass
#找到圖片所在的div
background_images=driver.find_elements_by_xpath(div)
location_list=[]
imageurl=''
for background_image in background_images:
location={}
#在html裡面解析出小圖片的url地址,還有長高的數值
location['x']=int(re.findall("background-image: url\(\"(.*)\"\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][1])
location['y']=int(re.findall("background-image: url\(\"(.*)\"\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][2])
imageurl=re.findall("background-image: url\(\"(.*)\"\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][0]
location_list.append(location)
imageurl=imageurl.replace("webp","jpg")
jpgfile=cStringIO.StringIO(urllib2.urlopen(imageurl).read())
#重新合併圖片
image=get_merge_image(jpgfile,location_list )
return image
def is_similar(image1,image2,x,y):
'''
對比RGB值
'''
pass
pixel1=image1.getpixel((x,y))
pixel2=image2.getpixel((x,y))
for i in range(0,3):
if abs(pixel1[i]-pixel2[i])>=50:
return False
return True
def get_diff_location(image1,image2):
'''
計算缺口的位置
'''
i=0
for i in range(0,260):
for j in range(0,116):
if is_similar(image1,image2,i,j)==False:
return  i
def get_track(length):
'''
根據缺口的位置模擬x軸移動的軌跡
'''
pass
list=[]
#     間隔通過隨機範圍函式來獲得
x=random.randint(1,3)
while length-x>=5:
list.append(x)
length=length-x
x=random.randint(1,3)
for i in xrange(length):
list.append(1)
return list
def main():
binary = FirefoxBinary('E:\\basic softer\\firefox.exe')
driver = webdriver.Firefox(firefox_binary=binary,executable_path='C:/Users/Administrator/Desktop/spyder/geckodriver.exe')
#     開啟網頁
driver.get("http://www.jianshu.com/sign_in")
#     等待頁面的上元素重新整理出來
WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath("//div[@class='gt_slider_knob gt_show']").is_displayed())
#     找到滑動的圓球
element = driver.find_element_by_xpath("//div[@class='gt_slider_knob gt_show']")
location = element.location
#     獲得滑動圓球的高度
y = location['y']
#     滑鼠點選元素並按住不放
print "第一步,點選元素"
ActionChains(driver).click_and_hold(on_element=element).perform()
time.sleep(0.15)
WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath("//div[@class='gt_cut_bg gt_show']").is_displayed())
WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath("//div[@class='gt_cut_fullbg gt_show']").is_displayed())
#     下載圖片
image1=get_image(driver, "//div[@class='gt_cut_bg gt_show']/div")
image2=get_image(driver, "//div[@class='gt_cut_fullbg gt_show']/div")
#     計算缺口位置
loc=get_diff_location(image1, image2)
#     生成x的移動軌跡點
track_list=get_track(loc)
print "第二步,拖動元素"
track_string = ""
for track in track_list:
track_string = track_string   "{%d,%d}," % (track, y - 445)
#         xoffset=track 22:這裡的移動位置的值是相對於滑動圓球左上角的相對值,而軌跡變數裡的是圓球的中心點,所以要加上圓球長度的一半。
#         yoffset=y-445:這裡也是一樣的。不過要注意的是不同的瀏覽器渲染出來的結果是不一樣的,要保證最終的計算後的值是22,也就是圓球高度的一半
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=track 22, yoffset=y-445).perform()
#         間隔時間也通過隨機函式來獲得
time.sleep(random.randint(10,50)/100)
print track_string
#     xoffset=21,本質就是向後退一格。這裡退了5格是因為圓球的位置和滑動條的左邊緣有5格的距離
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=21, yoffset=y-445).perform()
time.sleep(0.1)
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=21, yoffset=y-445).perform()
time.sleep(0.1)
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=21, yoffset=y-445).perform()
time.sleep(0.1)
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=21, yoffset=y-445).perform()
time.sleep(0.1)
ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=21, yoffset=y-445).perform()
print "第三步,釋放滑鼠"
#     釋放滑鼠
ActionChains(driver).release(on_element=element).perform()
time.sleep(3)
if __name__ == '__main__':
pass
main()