python - 模擬滑動(dòng)驗(yàn)證碼,有源碼,求解
問(wèn)題描述
# -*- coding:utf-8 -*-from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.common.action_chains import ActionChainsimport PIL.Image as imageimport time,re, randomimport requeststry: from StringIO import StringIOexcept ImportError: from io import StringIO#爬蟲(chóng)模擬的瀏覽器頭部信息agent = 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'headers = {'User-Agent': agent}# 根據(jù)位置對(duì)圖片進(jìn)行合并還原# filename:圖片# location_list:圖片位置#內(nèi)部?jī)蓚€(gè)圖片處理函數(shù)的介紹#crop函數(shù)帶的參數(shù)為(起始點(diǎn)的橫坐標(biāo),起始點(diǎn)的縱坐標(biāo),寬度,高度)#paste函數(shù)的參數(shù)為(需要修改的圖片,粘貼的起始點(diǎn)的橫坐標(biāo),粘貼的起始點(diǎn)的縱坐標(biāo))def get_merge_image(filename,location_list): #打開(kāi)圖片文件 im = image.open(filename) #創(chuàng)建新的圖片,大小為260*116 new_im = image.new('RGB', (260,116)) im_list_upper=[] im_list_down=[] # 拷貝圖片 for location in location_list:#上面的圖片if location['y']==-58: im_list_upper.append(im.crop((abs(location['x']),58,abs(location['x'])+10,166)))#下面的圖片if location['y']==0: 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#下載并還原圖片# driver:webdriver# p:圖片的pdef get_image(driver,p): #找到圖片所在的p background_images=driver.find_elements_by_xpath(p) location_list=[] imageurl='' #圖片是被CSS按照位移的方式打亂的,我們需要找出這些位移,為后續(xù)還原做好準(zhǔn)備 for background_image in background_images:location={}#在html里面解析出小圖片的url地址,還有長(zhǎng)高的數(shù)值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) #替換圖片的后綴,獲得圖片的URL imageurl=imageurl.replace('webp','jpg') #獲得圖片的名字 imageName = imageurl.split('/')[-1] #獲得圖片 session = requests.session() r = session.get(imageurl, headers = headers, verify = False) #下載圖片 with open(imageName, 'wb') as f:f.write(r.content)f.close() #重新合并還原圖片 image=get_merge_image(imageName, location_list) return image#對(duì)比RGB值def is_similar(image1,image2,x,y): pass #獲取指定位置的RGB值 pixel1=image1.getpixel((x,y)) pixel2=image2.getpixel((x,y)) for i in range(0,3):# 如果相差超過(guò)50則就認(rèn)為找到了缺口的位置if abs(pixel1[i]-pixel2[i])>=50: return False return True#計(jì)算缺口的位置def get_diff_location(image1,image2): i=0 # 兩張?jiān)紙D的大小都是相同的260*116 # 那就通過(guò)兩個(gè)for循環(huán)依次對(duì)比每個(gè)像素點(diǎn)的RGB值 # 如果相差超過(guò)50則就認(rèn)為找到了缺口的位置 for i in range(0,260):for j in range(0,116): if is_similar(image1,image2,i,j)==False:return i#根據(jù)缺口的位置模擬x軸移動(dòng)的軌跡def get_track(length): pass list=[] #間隔通過(guò)隨機(jī)范圍函數(shù)來(lái)獲得,每次移動(dòng)一步或者兩步 x=random.randint(1,3) #生成軌跡并保存到list內(nèi) while length-x>=5:list.append(x)length=length-xx=random.randint(1,3) #最后五步都是一步步移動(dòng) for i in range(length):list.append(1) return list#滑動(dòng)驗(yàn)證碼破解程序def main(): #打開(kāi)火狐瀏覽器 driver = webdriver.Firefox() #用火狐瀏覽器打開(kāi)網(wǎng)頁(yè) driver.get('http://www.geetest.com/exp_embed') #等待頁(yè)面的上元素刷新出來(lái) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_slider_knob gt_show']').is_displayed()) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_cut_bg gt_show']').is_displayed()) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_cut_fullbg gt_show']').is_displayed()) #下載圖片 image1=get_image(driver, '//p[@class='gt_cut_bg gt_show']/p') image2=get_image(driver, '//p[@class='gt_cut_fullbg gt_show']/p') #計(jì)算缺口位置 loc=get_diff_location(image1, image2) #生成x的移動(dòng)軌跡點(diǎn) track_list=get_track(loc) #找到滑動(dòng)的圓球 element=driver.find_element_by_xpath('//p[@class='gt_slider_knob gt_show']') location=element.location #獲得滑動(dòng)圓球的高度 y=location['y'] #鼠標(biāo)點(diǎn)擊元素并按住不放 print ('第一步,點(diǎn)擊元素') ActionChains(driver).click_and_hold(on_element=element).perform() time.sleep(0.15) print ('第二步,拖動(dòng)元素') track_string = '' for track in track_list:#不能移動(dòng)太快,否則會(huì)被認(rèn)為是程序執(zhí)行track_string = track_string + '{%d,%d},' % (track, y - 445)#xoffset=track+22:這里的移動(dòng)位置的值是相對(duì)于滑動(dòng)圓球左上角的相對(duì)值,而軌跡變量里的是圓球的中心點(diǎn),所以要加上圓球長(zhǎng)度的一半。#yoffset=y-445:這里也是一樣的。不過(guò)要注意的是不同的瀏覽器渲染出來(lái)的結(jié)果是不一樣的,要保證最終的計(jì)算后的值是22,也就是圓球高度的一半ActionChains(driver).move_to_element_with_offset(to_element=element, xoffset=track+22, yoffset=y-445).perform()#間隔時(shí)間也通過(guò)隨機(jī)函數(shù)來(lái)獲得,間隔不能太快,否則會(huì)被認(rèn)為是程序執(zhí)行time.sleep(random.randint(10,50)/100) print (track_string) #xoffset=21,本質(zhì)就是向后退一格。這里退了5格是因?yàn)閳A球的位置和滑動(dòng)條的左邊緣有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 ('第三步,釋放鼠標(biāo)') #釋放鼠標(biāo) ActionChains(driver).release(on_element=element).perform() time.sleep(3) #點(diǎn)擊驗(yàn)證 # submit = driver.find_element_by_xpath('//p[@class='gt_ajax_tip success']') # print(submit.location) # time.sleep(5) #關(guān)閉瀏覽器,為了演示方便,暫時(shí)注釋掉. #driver.quit()#主函數(shù)入口if __name__ == '__main__': pass main()
上面是一段源碼,模擬滑塊驗(yàn)證的,但是在
#等待頁(yè)面的上元素刷新出來(lái) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_slider_knob gt_show']').is_displayed()) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_cut_bg gt_show']').is_displayed()) WebDriverWait(driver, 30).until(lambda the_driver: the_driver.find_element_by_xpath('//p[@class='gt_cut_fullbg gt_show']').is_displayed())
這一段是,報(bào)無(wú)效語(yǔ)法,沒(méi)看出來(lái),大神說(shuō)下。以上源代碼來(lái)源于網(wǎng)絡(luò)。
問(wèn)題解答
回答1:沒(méi)有使用ide?
編輯器也可以啊!
把find_element_by_xpath('//p[@class='gt_slider_knob gt_show']')改成這樣find_element_by_xpath(’//p[@class='gt_slider_knob gt_show']’)
