Python爬蟲學習筆記(七) — 處理圖片驗證碼

文字驗證碼

安裝

pip install pytesseract
pip install tesseract-ocr

匯入模組

try:
from PIL import Image
except ImportError:
import Image
import pytesseract

(1)處理黑白的數字圖片

captcha = Image.open("captcha1.png")           #黑白圖片
result = pytesseract.image_to_string(captcha)
print(result)

(2)處理彩色的數字圖片

def convert_img(img,threshold):
img = img.convert("L") # 處理灰白
pixels = img.load()
for x in range(img.width):
for y in range(img.height):
if pixels[x, y] > threshold:
pixels[x, y] = 255
else:
pixels[x, y] = 0
return img
convert_img(captcha,150)
result = pytesseract.image_to_string(result)
print(result)

(3)處理有雜訊的數字圖片

data = img.getdata()
w,h = img.size
count = 0
for x in range(1,h-1):
for y in range(1, h - 1):
# 找出各个像素方向
mid_pixel = data[w * y + x]
if mid_pixel == 0:
top_pixel = data[w * (y - 1) + x]
left_pixel = data[w * y + (x - 1)]
down_pixel = data[w * (y + 1) + x]
right_pixel = data[w * y + (x + 1)]
if top_pixel == 0:
count += 1
if left_pixel == 0:
count += 1
if down_pixel == 0:
count += 1
if right_pixel == 0:
count += 1
if count > 4:
img.putpixel((x, y), 0)
result = pytesseract.image_to_string(captcha)
print(result)

圖片滑動驗證碼

使用Selenium -以Bilibili為例

import time
import requests
from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import re
from io import BytesIO
driver = webdriver.Chrome('/usr/lib/chromium-browser/chromedriver')
WAIT = WebDriverWait(driver, 10)
url = 'https://passport.bilibili.com/login'
def mergy_Image(image_file, location_list):
"""
将原始图片进行合成
:param image_file: 图片文件
:param location_list: 图片位置
:return: 合成新的图片
"""
# 存放上下部分的各个小块
upper_half_list = []
down_half_list = []
image = Image.open(image_file)# 通过 y 的位置来判断是上半部分还是下半部分,然后切割
for location in location_list:
if location['y'] == -58:
# 间距为10,y:58-116
im = image.crop((abs(location['x']), 58, abs(location['x'])+10, 116))
upper_half_list.append(im)
if location['y'] == 0:
# 间距为10,y:0-58
im = image.crop((abs(location['x']), 0, abs(location['x']) + 10, 58))
down_half_list.append(im)
# 创建一张大小一样的图片
new_image = Image.new('RGB', (260, 116))
# 粘贴好上半部分 y坐标是从上到下(0-116)
offset = 0
for im in upper_half_list:
new_image.paste(im, (offset, 0))
offset += 10
# 粘贴好下半部分
offset = 0
for im in down_half_list:
new_image.paste(im, (offset, 58))
offset += 10
return new_imagedef get_distance(bg_Image, fullbg_Image):# 阈值
threshold = 200
print(bg_Image.size[0])
print(bg_Image.size[1])
for i in range(60, bg_Image.size[0]):
for j in range(bg_Image.size[1]):
bg_pix = bg_Image.getpixel((i, j))
fullbg_pix = fullbg_Image.getpixel((i, j))
r = abs(bg_pix[0] - fullbg_pix[0])
g = abs(bg_pix[1] - fullbg_pix[1])
b = abs(bg_pix[2] - fullbg_pix[2])
if r + g + b > threshold:
return i
def get_path(distance):
result = []
current = 0
mid = distance * 4 / 5
t = 0.2
v = 0
while current < (distance - 10):
if current < mid:
a = 2
else:
a = -3
v0 = v
v = v0 + a * t
s = v0 * t + 0.5 * a * t * t
current += s
result.append(round(s))
return result
def start_drag(driver, distance):# 被妖怪吃掉了
# knob = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show")))
# ActionChains(driver).click_and_hold(knob).perform()
# ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0.1).perform()
# time.sleep(0.5)
# ActionChains(driver).release(knob).perform()
# 被妖怪吃掉了
# ActionChains(driver).drag_and_drop_by_offset(knob, distance-10, 0).perform()
knob = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show")))
result = get_path(distance)
ActionChains(driver).click_and_hold(knob).perform()
for x in result:
ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform()
time.sleep(0.5)
ActionChains(driver).release(knob).perform()
def recognize_code(driver):
"""
识别滑动验证码
:param driver: selenium驱动
:return:
"""
bs = BeautifulSoup(driver.page_source,'lxml')
# 找到背景图片和缺口图片的div
bg_div = bs.find_all(class_='gt_cut_bg_slice')
fullbg_div = bs.find_all(class_='gt_cut_fullbg_slice')
# 获取缺口背景图片url
bg_url = re.findall('background-image:\surl\("(.*?)"\)',bg_div[0].get('style'))
# 获取背景图片url
fullbg_url = re.findall('background-image:\surl\("(.*?)"\)',fullbg_div[0].get('style'))
# 存放每个合成缺口背景图片的位置
bg_location_list = []
# 存放每个合成背景图片的位置
fullbg_location_list = []
for bg in bg_div:
location = {}
location['x'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', bg.get('style'))[0][0])
location['y'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', bg.get('style'))[0][1])
bg_location_list.append(location)
for fullbg in fullbg_div:
location = {}
location['x'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', fullbg.get('style'))[0][0])
location['y'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', fullbg.get('style'))[0][1])
fullbg_location_list.append(location)
print(bg_location_list)
print(fullbg_location_list)
# 将图片格式存为 jpg 格式
bg_url = bg_url[0].replace('webp', 'jpg')
fullbg_url = fullbg_url[0].replace('webp', 'jpg')
# print(bg_url)
# print(fullbg_url)
# 下载图片
bg_image = requests.get(bg_url).content
fullbg_image = requests.get(fullbg_url).content
print('完成图片下载')
# 写入图片
bg_image_file = BytesIO(bg_image)
fullbg_image_file = BytesIO(fullbg_image)
# 合成图片
bg_Image = mergy_Image(bg_image_file, bg_location_list)
fullbg_Image = mergy_Image(fullbg_image_file, fullbg_location_list)
# bg_Image.show()
# fullbg_Image.show()
# 计算缺口偏移距离
distance = get_distance(bg_Image, fullbg_Image)
print('得到距离:%s' % str(distance))
start_drag(driver, distance)if __name__ == '__main__':# 获取滑块按钮
driver.get(url)
slider = WAIT.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show")))
recognize_code(driver)# driver.close()

https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484321&idx=1&sn=4bc73324acfacda7d3bc82120b19d11a&scene=19#wechat_redirect

Written by

Machine Learning / Deep Learning / Python / Flutter cakeresume.com/yanwei-liu

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store