
弹窗图片中的文字是定位交互区域的关键标识,需通过光学字符识别(OCR)技术提取文本并确定位置。Tesseract-OCR 作为开源高效的 OCR 引擎,支持多语言识别且可通过训练优化精度,配合 Python 的 pytesseract 库可快速实现图片文本检测。同时,OpenCV 用于图片预处理(降噪、二值化),提升 OCR 识别准确率。
网页弹窗本质是 DOM 元素的动态渲染,通过 Selenium 模拟浏览器环境,可捕获弹窗对应的 HTML 节点。结合文本检测结果,将 OCR 识别到的目标文本(如 “拖动滑块”)与弹窗图片中的坐标关联,定位滑块起始位置与目标区域(通常为文本提示对应的缺口位置)。
滑块拖动需模拟人类操作轨迹,避免被反爬机制识别为机器行为。核心是生成非线性移动轨迹(加速 - 匀速 - 减速),通过 Selenium 的 ActionChains 类实现鼠标按下、移动、释放的连贯操作,同时控制移动时间与步长,模拟真实用户交互。
需安装以下 Python 库,分别用于浏览器模拟、图片处理、OCR 识别及轨迹生成:
# 浏览器自动化库
pip install selenium
# 图片处理库
pip install opencv-python
# OCR识别库
pip install pytesseract
# 图像处理辅助库
pip install pillow
# 数值计算库(用于轨迹生成)
pip install numpyC:\Program Files\Tesseract-OCR),确保命令行输入tesseract --version可正常返回版本。python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import cv2
import pytesseract
from PIL import Image
import numpy as np
import time
# 配置Tesseract路径(Windows系统需指定)
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
class SlideVerificationCrawler:
def __init__(self, url):
# 初始化Chrome浏览器(无头模式可选)
self.options = webdriver.ChromeOptions()
self.options.add_experimental_option("excludeSwitches", ["enable-automation"])
self.options.add_experimental_option('useAutomationExtension', False)
self.driver = webdriver.Chrome(options=self.options)
self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
self.url = url
self.wait = WebDriverWait(self.driver, 10)
def open_page(self):
"""打开目标网页"""
self.driver.get(self.url)
self.driver.maximize_window()
# 等待页面加载完成(根据实际网页调整等待条件)
self.wait.until(EC.presence_of_element_located((By.TAG_NAME, 'body')))
print("网页加载完成")python
def capture_popup_image(self, popup_img_xpath):
"""捕获弹窗图片"""
# 等待弹窗图片加载
popup_img = self.wait.until(EC.presence_of_element_located((By.XPATH, popup_img_xpath)))
# 获取图片位置与尺寸
location = popup_img.location
size = popup_img.size
# 浏览器截图
self.driver.save_screenshot('full_screen.png')
# 裁剪弹窗图片
full_img = Image.open('full_screen.png')
left = location['x']
top = location['y']
right = left + size['width']
bottom = top + size['height']
popup_img_crop = full_img.crop((left, top, right, bottom))
popup_img_path = 'popup_image.png'
popup_img_crop.save(popup_img_path)
print(f"弹窗图片已保存至{popup_img_path}")
return popup_img_path
def preprocess_image(self, img_path):
"""图片预处理:降噪、二值化提升OCR准确率"""
img = cv2.imread(img_path)
# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯模糊降噪
blur = cv2.GaussianBlur(gray, (3, 3), 0)
# 自适应二值化
thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2)
# 保存预处理后的图片
preprocessed_img_path = 'preprocessed_image.png'
cv2.imwrite(preprocessed_img_path, thresh)
return preprocessed_img_pathpython
def detect_text(self, img_path):
"""OCR文本检测:返回识别文本及对应坐标"""
img = Image.open(img_path)
# 配置Tesseract识别参数(中文识别+返回坐标)
custom_config = r'--oem 3 --psm 6 -l chi_sim+eng makebox'
# 执行OCR识别
result = pytesseract.image_to_data(img, config=custom_config, output_type=pytesseract.Output.DICT)
# 提取有效文本(过滤空字符串)
text_info = []
for i in range(len(result['text'])):
text = result['text'][i].strip()
if text:
# 获取文本区域坐标(left, top, width, height)
left = result['left'][i]
top = result['top'][i]
width = result['width'][i]
height = result['height'][i]
text_info.append({
'text': text,
'left': left,
'top': top,
'width': width,
'height': height,
'center_x': left + width // 2,
'center_y': top + height // 2
})
print(f"识别到的文本:{[info['text'] for info in text_info]}")
return text_info
def locate_target_area(self, text_info):
"""根据文本定位滑块起始位置与目标位置"""
start_pos = None
target_pos = None
for info in text_info:
# 假设“拖动滑块”对应滑块起始位置(可根据实际网页调整关键词)
if '拖动滑块' in info['text']:
start_pos = (info['center_x'], info['center_y'])
# 假设“缺口”对应目标位置(可根据实际网页调整关键词)
elif '缺口' in info['text']:
target_pos = (info['center_x'], info['center_y'])
if not start_pos or not target_pos:
raise Exception("未识别到关键文本,无法定位目标区域")
print(f"滑块起始位置:{start_pos},目标位置:{target_pos}")
return start_pos, target_pospython
def generate_track(self, distance):
"""生成模拟人类的滑块拖动轨迹(非线性)"""
track = []
current = 0
# 加速阶段(前30%距离)
accelerate_distance = distance * 0.3
while current < accelerate_distance:
# 加速度逐渐减小
a = np.random.uniform(1.5, 2.5)
v = current + a
track.append(round(v))
current += v
# 匀速阶段(中间50%距离)
uniform_distance = distance * 0.5
while current < accelerate_distance + uniform_distance:
v = np.random.uniform(2.0, 3.0)
track.append(round(v))
current += v
# 减速阶段(最后20%距离)
while current < distance:
a = np.random.uniform(0.5, 1.0)
v = max(0.5, current - (distance - current) * a)
track.append(round(v))
current += v
# 确保总距离准确
track = track[:-1] if sum(track) > distance else track
track.append(distance - sum(track))
return track
def drag_slider(self, slider_xpath, start_pos, target_pos):
"""执行滑块拖动操作"""
# 定位滑块元素
slider = self.wait.until(EC.presence_of_element_located((By.XPATH, slider_xpath)))
# 计算水平拖动距离(假设垂直方向无需移动)
distance = target_pos[0] - start_pos[0]
if distance <= 0:
raise Exception("目标位置在起始位置左侧,距离计算错误")
# 生成拖动轨迹
track = self.generate_track(distance)
print(f"拖动轨迹:{track},总距离:{sum(track)}")
# 模拟鼠标操作
action = ActionChains(self.driver)
# 鼠标移动到滑块起始位置并按下
action.move_to_element_with_offset(slider, start_pos[0], start_pos[1])
action.click_and_hold().perform()
time.sleep(0.2) # 按下后停留0.2秒,模拟人类操作
# 按轨迹移动鼠标
for step in track:
action.move_by_offset(step, np.random.randint(-2, 3)) # 垂直方向随机小幅度抖动
action.perform()
time.sleep(np.random.uniform(0.01, 0.03)) # 每步停留随机时间
# 释放鼠标
action.release().perform()
time.sleep(1) # 等待验证结果python
运行
def run(self, popup_img_xpath, slider_xpath):
"""执行完整爬虫与验证流程"""
try:
# 1. 打开网页
self.open_page()
# 2. 触发弹窗(根据实际网页调整,如点击按钮)
# 示例:self.driver.find_element(By.XPATH, '//button[@id="verify-btn"]').click()
time.sleep(2) # 假设弹窗自动弹出,等待2秒
# 3. 捕获弹窗图片
popup_img_path = self.capture_popup_image(popup_img_xpath)
# 4. 图片预处理
preprocessed_img_path = self.preprocess_image(popup_img_path)
# 5. 文本检测
text_info = self.detect_text(preprocessed_img_path)
# 6. 定位目标区域
start_pos, target_pos = self.locate_target_area(text_info)
# 7. 拖动滑块
self.drag_slider(slider_xpath, start_pos, target_pos)
# 8. 验证结果校验(根据实际网页调整判断条件)
if "验证成功" in self.driver.page_source:
print("滑块验证成功!")
else:
print("验证失败,重试中...")
self.run(popup_img_xpath, slider_xpath) # 重试
except Exception as e:
print(f"执行失败:{str(e)}")
finally:
# 保持浏览器打开,便于调试(生产环境可注释)
time.sleep(10)
self.driver.quit()
# 示例:调用爬虫(需根据实际网页调整XPATH)
if __name__ == "__main__":
target_url = "https://example.com/verify-page" # 目标网页URL
# 弹窗图片XPATH(需根据实际网页F12查看)
popup_img_xpath = '//div[@class="popup-img"]/img'
# 滑块元素XPATH(需根据实际网页F12查看)
slider_xpath = '//div[@class="slider-block"]'
crawler = SlideVerificationCrawler(target_url)
crawler.run(popup_img_xpath, slider_xpath)in关键字或正则表达式),提高关键文本识别容错率。webdriver标识,通过 CDP 命令修改navigator.webdriver属性,避免被网页检测为爬虫。WebDriverWait等待图片naturalWidth属性大于 0。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。