📜  Python Web爬网-处理验证码(1)

📅  最后修改于: 2023-12-03 15:34:06.108000             🧑  作者: Mango

Python Web爬网-处理验证码

当我们使用Python进行网络爬虫时,有些网站为了防止机器爬取造成影响,会在登录或执行某些操作时,弹出验证码。如何在Python中处理验证码呢?

一、验证码的类型

常见的验证码类型有以下几种:

  1. 图片验证码:使用图像来展示文字或数字,常常需要用户进行识别或计算,然后填写到输入框中,以验证用户的身份。图片验证码有时会添加一些干扰线、干扰点等,以减少机器破解的可能性。

  2. 滑块验证码:需要用户通过鼠标或手指滑动一个滑块,将其拖动到指定的位置,以验证用户的身份。

  3. 语音验证码:播放一段语音,需要用户倾听并输入其中的数字或文字,以验证用户的身份。

  4. 短信验证码:将验证码通过短信发送到用户的手机上,需要用户手动输入验证码,以验证身份。

二、验证码处理方法
  1. 图片验证码

对于图片验证码,我们可以使用Python中的PIL库进行处理。具体流程如下:

1)将验证码图片下载到本地,使用PIL库进行打开。

from PIL import Image
import requests
from io import BytesIO

# 下载验证码图片
response = requests.get(url, headers=headers)
image = Image.open(BytesIO(response.content))

2)通过PIL库的ImageEnhance模块,加强图片的对比度,使文字更加清晰。

from PIL import ImageEnhance

# 增强图片对比度
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(2)

3)使用pytesseract库识别图片中的文字。

import pytesseract

# 识别图片中的文字
text = pytesseract.image_to_string(image)

4)将识别出的文字填写到验证码输入框中即可。需要注意的是,由于验证码中往往包含的是随机字母或数字,因此需要对识别出的文字进行清洗,只保留数字或字母。

# 清洗识别出的文字
text = ''.join(filter(str.isalnum, text))
  1. 滑块验证码

对于滑块验证码,我们可以使用第三方库selenium模拟用户鼠标的滑动操作。具体流程如下:

1)使用selenium打开网页,并定位到滑块所在的元素。

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

# 初始化Chrome浏览器
driver = webdriver.Chrome()

# 打开网页
driver.get(url)

# 定位到滑块所在的元素
slider = driver.find_element_by_xpath(xpath)

2)将页面截取下来(不包含滑块),作为无滑块的背景图。

# 截取页面(不包含滑块),作为无滑块的背景图
background_image = driver.get_screenshot_as_png()
background_image = Image.open(BytesIO(background_image))

left, top, right, bottom = slider.location['x'], slider.location['y'], slider.location['x']+slider.size['width'], slider.location['y']+slider.size['height']
slider_image = background_image.crop((left, top, right, bottom))

background_image.save('background.png')  # 保存背景图
slider_image.save('slider.png')  # 保存滑块图片 

3)通过PIL库的ImageGrab模块,截取整个滑块(包含背景)的图片。

from PIL import ImageGrab

# 截取整个滑块(包含背景)的图片
slider_position = slider.location_once_scrolled_into_view
slider_image = ImageGrab.grab((slider_position['x'], slider_position['y'], slider_position['x']+slider.size['width'], slider_position['y']+slider.size['height']))
slider_image.save('slider_all.png')  # 保存整个滑块图片

4)通过第三方库opencv(cv2)进行滑块的精准匹配。

需要注意:对于滑块图片和背景图片,需要转换为灰度图,并对其进行模糊处理,以减少匹配的差异。

import cv2 as cv

# 转换为灰度图
background_gray = cv.cvtColor(np.array(background_image), cv.COLOR_RGB2GRAY)
slider_gray = cv.cvtColor(np.array(slider_image), cv.COLOR_RGB2GRAY)

# 对图片进行模糊处理
background_blur = cv.GaussianBlur(background_gray, (5, 5), 0)
slider_blur = cv.GaussianBlur(slider_gray, (5, 5), 0)

# 进行滑块的精准匹配
match_result = cv.matchTemplate(background_blur, slider_blur, cv.TM_CCOEFF_NORMED)

5)通过滑块的最佳匹配位置算出滑块需要滑动的距离,并将鼠标移动到该位置进行点击滑动。

slider_position = np.unravel_index(np.argmax(match_result), match_result.shape)

# 计算滑块需要滑动的距离
distance = slider_position[1] - left

# 按下鼠标左键
ActionChains(driver).click_and_hold(slider).perform()

# 模拟鼠标移动
for i in range(distance):
    ActionChains(driver).move_by_offset(1, 0).perform()

# 释放鼠标左键
ActionChains(driver).release().perform()

在滑动滑块时,由于每个网站的滑块操作不一样,因此需要对不同的滑块进行调试和适配。

三、参考资料
  1. Python爬虫如何破解验证码(1)—— 图片验证码

  2. Python爬虫如何破解验证码(2)—— 滑块验证码

  3. Python图像处理库Pillow(PIL)详解

  4. Python+Selenium:自动化Web测试详解

  5. opencv-python官方文档