深夜免費(fèi)軟件app下載seo營銷的概念
由于最近比較忙,所以本周搞了一個相對簡單的驗證碼,就是抖音Tiktok的滑塊驗證碼,這也是接到客戶的一個需求。這種驗證碼通常在電腦端登錄抖音、巨量引擎的的時候出現(xiàn)。
首先看一下最終的效果:
?
驗證碼識別過程
1、利用爬蟲采集圖像
由于是識別滑塊缺口位置,分析了一下,大圖已經(jīng)包含了滑塊缺口的位置信息,所以這里只需要采集大圖就夠了。不需要小圖進(jìn)行比對,這樣可以簡單一點(diǎn)。
(1)采集大圖
2、人工標(biāo)記
為了保障識別的精度,這里需要進(jìn)行大量的人工標(biāo)記,最好將誤差控制在1-2像素以內(nèi),這樣訓(xùn)練出來的識別模型效果才好。
?3、訓(xùn)練模型
4、測試驗證
我們將訓(xùn)練好的模型用100張圖片來進(jìn)行測試,發(fā)現(xiàn)全部都能正確識別位置,所以正確率接近100%。因為100張測試圖片比較少,所以保守估計正確率應(yīng)該在99%左右。
如果再想提升正確率,可以再增加訓(xùn)練的數(shù)據(jù)量,就需要再投入大量人力,這個投入與提升產(chǎn)出比需要自己權(quán)衡。
5、實(shí)戰(zhàn)測試
這里我就直接上代碼,就是文章開通動圖的演示效果。我也將模型封裝成了免費(fèi)的接口給感興趣的小伙伴調(diào)用:得塔云
__author__ = "dengxinyan"import io
import time
import json
import requests
import urllib
import random
import base64
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ChromeOptions
from selenium.webdriver import FirefoxOptions# PIL圖片保存為base64編碼
def PIL_base64(img, coding='utf-8'):img_format = img.formatif img_format == None:img_format = 'JPEG'format_str = 'JPEG'if 'png' == img_format.lower():format_str = 'PNG'if 'gif' == img_format.lower():format_str = 'gif'if img.mode == "P":img = img.convert('RGB')if img.mode == "RGBA":format_str = 'PNG'img_format = 'PNG'output_buffer = BytesIO()# img.save(output_buffer, format=format_str)img.save(output_buffer, quality=100, format=format_str)byte_data = output_buffer.getvalue()base64_str = 'data:image/' + img_format.lower() + ';base64,' + base64.b64encode(byte_data).decode(coding)return base64_str# 驗證碼識別接口
def shibie(img):url = "http://www.detayun.cn/openapi/verify_code_identify/"data = {# 用戶的key"key":"nWrzPFUgFuqXQrCJJUME",# 驗證碼類型"verify_idf_id":"6",# 樣例圖片"img_base64":PIL_base64(img),"img_byte": None,# 中文點(diǎn)選,空間語義類型驗證碼的文本描述(這里缺省為空字符串)"words":""}header = {"Content-Type": "application/json"}# 發(fā)送請求調(diào)用接口response = requests.post(url=url, json=data, headers=header)print(response.text)return response.json()def run(headless=False):# 配置參數(shù)options = FirefoxOptions()if headless:options.add_argument('--headless')else:options.add_argument('--window-size=100,100')options.add_argument('--disable-blink-features=AutomationControlled')options.add_argument('--disable-dev-shm-usage')options.set_preference('general.useragent.override', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36')driver = webdriver.Firefox(executable_path=r'F:\驗證碼項目\小紅書旋轉(zhuǎn)驗證碼\webdriver\geckodriver.exe', options=options)# 偽裝瀏覽器driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => false,});")navigator_webdriver = driver.execute_script("return navigator.webdriver")driver.execute_script("Object.defineProperty(navigator, 'plugins', {get: () => [1, 2, 3, 4, 5],});")plugins_length = driver.execute_script("return navigator.plugins.length")# 發(fā)送請求driver.get('https://business.oceanengine.com/login?appKey=51')# 等待【請輸入郵箱】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//input[@placeholder="請輸入郵箱"]'))# 找到【請輸入郵箱】元素tag1 = driver.find_element_by_xpath('//input[@placeholder="請輸入郵箱"]')# 點(diǎn)擊【請輸入郵箱】元素tag1.click()# 輸入郵箱tag1.send_keys('123451111@qq.com')# 等待【密碼】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//input[@placeholder="密碼"]'))# 找到【密碼】元素tag2 = driver.find_element_by_xpath('//input[@placeholder="密碼"]')# 點(diǎn)擊【密碼】元素tag2.click()# 輸入密碼tag2.send_keys('13611112222')# 等待【用戶協(xié)議】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="account-center-agreement-check"]'))# 找到【用戶協(xié)議】元素tag3 = driver.find_element_by_xpath('//div[@class="account-center-agreement-check"]')# 點(diǎn)擊【用戶協(xié)議】元素tag3.click()# 等待【登錄】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//button[@class="ace-ui-btn account-center-action-button active ace-ui-btn-primary"]'))# 找到【登錄】元素tag4 = driver.find_element_by_xpath('//button[@class="ace-ui-btn account-center-action-button active ace-ui-btn-primary"]')# 點(diǎn)擊【登錄】元素tag4.click()# 可能一次不成功,需要多次滑動for i in range(5):# 等待【驗證碼大圖】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//img[@id="captcha-verify-image"]'))# 找到【驗證碼大圖】元素tag5 = driver.find_element_by_xpath('//img[@id="captcha-verify-image"]')# 獲取圖像鏈接img_url = tag5.get_attribute('src')print(img_url)header = {"Host": "p9-catpcha.byteimg.com","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Accept-Encoding": "gzip, deflate, br","Connection": "keep-alive","Upgrade-Insecure-Requests": "1",}# 下載圖片response = requests.get(url=img_url)img = Image.open(BytesIO(response.content))y = shibie(img)# 獲得滑動像素距離y = int(str(y['data']['res_str']).replace('滑動','').replace('px',''))# 等待【滑塊】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="secsdk-captcha-drag-icon sc-kEYyzF fiQtnm"]'))# 找到【滑塊】元素tag6 = driver.find_element_by_xpath('//div[@class="secsdk-captcha-drag-icon sc-kEYyzF fiQtnm"]')# 滑動滑塊action = ActionChains(driver)action.click_and_hold(tag6).perform()time.sleep(1)# 計算實(shí)際滑動距離 = 像素距離 * 滑動系數(shù)move_x = y * 0.61# 滑動1:直接滑動action.move_by_offset(move_x + 20, 5)time.sleep(0.5)action.move_by_offset(-10, -15)time.sleep(0.5)action.move_by_offset(-10, 10)# 滑動2:分段滑動# n = (random.randint(5, 8))# move_x = move_x / n# for i in range(n):# action.move_by_offset(move_x, 5)# time.sleep(0.5)time.sleep(1)# 釋放鼠標(biāo)action.release().perform()time.sleep(2)# 判斷是否滑動成功try:# 等待【錯誤提示】元素出現(xiàn)WebDriverWait(driver, 5).until(lambda x: x.find_element_by_xpath('//div[@class="sc-htoDjs jwiskW"]'))# 等待【刷新】元素出現(xiàn)WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//span[@class="secsdk_captcha_refresh--text sc-bwzfXH gBXrMn"]'))# 找到【刷新】元素tag7 = driver.find_element_by_xpath('//span[@class="secsdk_captcha_refresh--text sc-bwzfXH gBXrMn"]')# 點(diǎn)擊【刷新】元素tag7.click()time.sleep(1)except:breakif __name__ == '__main__':run(headless=False)
6、總結(jié)分析
(1)抖音圖片標(biāo)注工作比較復(fù)雜,我統(tǒng)計了一下背景圖的種類超過800中,所以給標(biāo)注、識別增加了一定難度
(2)抖音的滑動軌跡檢測比較厲害,直接滑動到位完全無法通過,分段軌跡也很難通過。所以我首先滑過,再返回對齊,這樣就能完美一次通過驗證(最前面動圖就是這樣的效果)
(3)抖音頁面有很強(qiáng)的反爬措施,檢測我使用 selenium 始終無法通過驗證,始終不會條驗證碼。這一點(diǎn)如何防檢測?selenium 也請各位大神指點(diǎn)。所以我代碼使用的巨量引擎(巨量引擎是字節(jié)跳動旗下的品牌)網(wǎng)站進(jìn)行的測試
各位大神也請指出我的不足,或者有其他建議都可以給我留言,或私信我,謝謝指點(diǎn)。
?