匠心精神 - 良心品质腾讯认可的专业机构-IT人的高薪实战学院

咨询电话:4000806560

精通Python爬虫:如何应对各种验证码?

精通Python爬虫:如何应对各种验证码?

在进行爬取网站数据时,我们难免会遇到各种验证码,如数字、文字、滑块、倒立文字、拖动验证等等。这些验证码是为了防止被机器人爬取而设置的安全措施。本文将介绍如何使用Python解决各种验证码问题。

1. 数字验证码

数字验证码是最简单的一种验证码,一般由0-9的数字组成。我们可以使用Python的Pillow库,通过图像处理技术识别出验证码内容。以下是一个示例代码:

```python
from PIL import Image
import pytesseract

img = Image.open('captcha.png')
img = img.convert('L')
text = pytesseract.image_to_string(img, config='digits')
print(text)
```

这段代码中,我们首先使用Pillow库打开验证码图片,然后将图片转为灰度图像,最后使用pytesseract库的image_to_string方法,将图像中的数字转为文本。config参数指定识别数字文本,如果验证码中包含字母,我们可以设置为'letters'。

2. 文字验证码

文字验证码由大小写字母和数字组成,一般较为复杂。我们可以使用CNN(卷积神经网络)模型进行训练,从而实现自动识别。以下是一个示例代码:

```python
import tensorflow as tf
import numpy as np
from PIL import Image

# 加载已训练的模型
model = tf.keras.models.load_model('captcha_model.h5')

# 预处理验证码图片
def preprocess_image(image_path):
    image = Image.open(image_path).convert('RGB')
    image = np.array(image)
    image = tf.image.resize(image, [150, 300])
    image /= 255.0
    return np.expand_dims(image, axis=0)

# 预测验证码
def predict_captcha(image_path):
    image = preprocess_image(image_path)
    pred = model.predict(image)
    return ''.join([chr(np.argmax(x)+97) for x in pred[0]])

# 测试
print(predict_captcha('captcha.png'))
```

这段代码中,我们首先加载了已经训练好的CNN模型。然后对验证码图片进行预处理,缩放到指定的大小,并将像素值归一化。最后使用模型的predict方法进行预测,将预测结果转为文本。

3. 滑块验证码

滑块验证码是现在比较常见的一种验证码,用户需要通过拖动滑块,将滑块移动到指定位置,才能通过验证。我们可以使用selenium库模拟用户操作,并通过比较滑块前后背景图像的相似度,确定滑块的位置。以下是一个示例代码:

```python
from selenium import webdriver
from PIL import Image
import time
import numpy as np

# 打开浏览器
driver = webdriver.Chrome()
driver.get('https://www.google.com/recaptcha/api2/demo')

# 等待验证码加载
while True:
    if driver.execute_script('return document.readyState') == 'complete':
        break
    time.sleep(1)
    
# 获取滑块和背景图片链接
slider_url = driver.find_element_by_css_selector('.rc-slider').get_attribute('src')
bg_url = driver.find_element_by_css_selector('.rc-imageselect-target').get_attribute('src')

# 下载图片
def download_image(url):
    driver.get(url)
    image = driver.find_element_by_tag_name('img')
    src = image.get_attribute('src')
    return Image.open(requests.get(src, stream=True).raw)

slider_image = download_image(slider_url)
bg_image = download_image(bg_url)

# 计算滑块位置
def get_position():
    slider = np.array(slider_image.convert('L'))
    bg = np.array(bg_image.convert('L'))
    threshold = 100
    diff = np.abs(slider-bg)
    for i in range(diff.shape[0]):
        if np.sum(diff[i,:]) > threshold:
            return i

# 模拟滑动操作
def slide_to(position):
    slider = driver.find_element_by_css_selector('.rc-slider-handle')
    actions = webdriver.ActionChains(driver)
    actions.click_and_hold(slider).perform()
    for _ in range(position):
        actions.move_by_offset(1, 0).perform()
    actions.release().perform()

# 执行验证码识别
position = get_position()
print('滑块位置:', position)
slide_to(position)
```

这段代码中,我们首先使用selenium库打开一个recaptcha演示网页,并等待验证码加载完成。然后获取滑块和背景图片的链接,并进行下载。最后通过比较滑块和背景图像的相似度,确定滑块位置,模拟滑动操作,完成验证码识别。

4. 倒立文字验证码

倒立文字验证码是为了防止机器人爬取而设置的一种复杂验证码,文字呈倒立状态,一般需要翻转或旋转才能正确识别。我们可以使用图像处理技术将文本翻转或旋转至正常状态,再进行识别。以下是一个示例代码:

```python
from PIL import Image
import pytesseract

# 加载已训练的模型
model = load_model('captcha_model.h5')

# 预处理验证码图片
def preprocess_image(image_path):
    image = Image.open(image_path).convert('L')
    image = image.resize((image.width*5, image.height*5))
    image = ImageOps.invert(image)
    return np.array(image)

# 反转倒立文本
def invert_text(img):
    inv_img = ImageOps.invert(img)
    text_img = Image.new('L', inv_img.size, 255)
    text_img.paste(inv_img, (0, inv_img.height//2))
    angle = pytesseract.image_to_osd(text_img)['rotate']
    return text_img.rotate(-angle, resample=Image.BICUBIC, fillcolor=255)

# 预测验证码
def predict_captcha(image_path):
    image = preprocess_image(image_path)
    text_img = invert_text(Image.fromarray(image))
    text = pytesseract.image_to_string(text_img)
    return text

# 测试
print(predict_captcha('captcha.png'))
```

这段代码中,我们首先加载已经训练好的CNN模型。然后对验证码图片进行预处理,将图像缩放,并将像素值反转。接着使用pytesseract库的image_to_osd方法,获取倒立文本的旋转角度。最后将文本图像旋转至正常状态,使用pytesseract库的image_to_string方法,将文本转为字符串。