📅  最后修改于: 2023-12-03 15:34:06.108000             🧑  作者: Mango
当我们使用Python进行网络爬虫时,有些网站为了防止机器爬取造成影响,会在登录或执行某些操作时,弹出验证码。如何在Python中处理验证码呢?
常见的验证码类型有以下几种:
图片验证码:使用图像来展示文字或数字,常常需要用户进行识别或计算,然后填写到输入框中,以验证用户的身份。图片验证码有时会添加一些干扰线、干扰点等,以减少机器破解的可能性。
滑块验证码:需要用户通过鼠标或手指滑动一个滑块,将其拖动到指定的位置,以验证用户的身份。
语音验证码:播放一段语音,需要用户倾听并输入其中的数字或文字,以验证用户的身份。
短信验证码:将验证码通过短信发送到用户的手机上,需要用户手动输入验证码,以验证身份。
对于图片验证码,我们可以使用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))
对于滑块验证码,我们可以使用第三方库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()
在滑动滑块时,由于每个网站的滑块操作不一样,因此需要对不同的滑块进行调试和适配。