目前在学习网络爬虫中的验证码识别,今天做了个有趣的项目,用超级鹰来模拟登陆超级鹰。
超级鹰:验证码服务平台,提供验证码识别服务。
selenium:最广泛使用的开源 Web UI(用户界面)自动化测试套件之一,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到所谓的“可见及爬”,是网络爬虫中的一把利器。
crop()函数: 用于裁剪图片,使用Image中的open(file)方法可返回一个打开的图片,使用crop([x1,y1,x2,y2])可进行裁剪。
初始化信息
输入用户信息
获取验证码图片对象
获取验证码位置
获取网页截图
获取验证码图片
登录按钮获取
模拟点击登录
验证积分
模拟登陆的难点之一在于对验证码的识别,识别部分这里交给超级鹰平台来处理,超级鹰的使用方法可以参考:超级鹰:selenium专门用来破解各种验证码_Shaun_X-CSDN博客,这里我们主要进行的是对验证码的定位及截取保存
presence_of_element_located:节点加载出来,传入定位元组,如(By.ID, 'p')
定位验证码元素
element = self.wait.until(EC.presence_of_element_located((By.XPATH,
'//body/div[3]/div[1]/div[3]/div[1]/form[1]/div[1]/img[1]')))
获取验证码位置
def captcha_position(self):
element = self.captcha_element()
time.sleep(2)
# 获取对象位置
location = element.location
# 获取图片大小
size = element.size
# 291, 291+50, 668, 668+180
top, bottom, left, right = location['y'], location['y'] + size[
'height'], \
location['x'], location['x'] + size['width']
return top, bottom, left, right
截取此时网页,以便于获取验证码
def browser_screenshot(self):
screenshot = self.browser.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
get_screenshot_as_png():以PNG格式保存截图
BytesIO:类文件对象(file-like object),这种对象在内存中创建,可以像文件一样被操作。StringIO只能存储字符串,遇到从网络下载的图片视频等Bytes类型的内容就不行了,需要用到专门存储Bytes类型的BytesIO对象
获取验证码图片
def captcha_img(self, name='captcha.png'):
top, bottom, left, right = self.captcha_position()
print("验证码的位置是:", top, bottom, left, right)
screenshot = self.browser_screenshot()
captcha = screenshot.crop(
(left * 1.25, top * 1.25, right * 1.25, bottom * 1.25))
captcha.save(name)
return captcha
crop()函数: 用于裁剪图片,使用Image中的open(file)方法可返回一个打开的图片,使用crop([x1,y1,x2,y2])可进行裁剪。
我在做这个项目时发现截取到的不是真正的验证码图片,研究测试了半天,发现这里的坐标应该全部乘1.25,因为电脑缩放与布局用的125%为推荐设置,设置→显示,可以将其调为100%或者我这种处理方式。
最后是整个项目的源代码,欢迎交流指正
# @Author : YJL
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from PIL import Image
from io import BytesIO
from chaojiying import Chaojiying_Client
# 这里输入注册超级鹰后的用户名、密码
USER_NAME = ''
PASSWORD = ''
# 这里是要识别的验证码类型
cjy_id = '1902'
class ChaojiyingLogin(object):
# 1.初始化信息
def __init__(self):
self.url = 'https://www.chaojiying.com/user/login/'
self.user = USER_NAME
self.pwd = PASSWORD
self.browser = webdriver.Chrome()
self.wait = WebDriverWait(self.browser, 10)
self.chaojiying = Chaojiying_Client(USER_NAME, PASSWORD, cjy_id)
# 2.输入用户信息
def input_info(self):
self.browser.get(self.url)
username = self.wait.until(EC.presence_of_element_located(
(By.XPATH, '//div[@class="login_form"]/form/p[1]/input')))
password = self.wait.until(EC.presence_of_element_located(
(By.XPATH, '//div[@class="login_form"]/form/p[2]/input')))
username.send_keys(self.user)
password.send_keys(self.pwd)
# 3.获取验证码图像对象
def captcha_element(self):
element = self.wait.until(EC.presence_of_element_located(
(By.XPATH,
'//body/div[3]/div[1]/div[3]/div[1]/form[1]/div[1]/img[1]')))
return element
# 4.获取验证码位置
def captcha_position(self):
element = self.captcha_element()
time.sleep(2)
location = element.location
size = element.size
# 291, 291+50, 668, 668+180
top, bottom, left, right = location['y'], location['y'] + size[
'height'], \
location['x'], location['x'] + size['width']
return top, bottom, left, right
# 5.获取网页截图
def browser_screenshot(self):
screenshot = self.browser.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
# 6.获取验证码图片
def captcha_img(self, name='captcha.png'):
top, bottom, left, right = self.captcha_position()
print("验证码的位置是:", top, bottom, left, right)
screenshot = self.browser_screenshot()
captcha = screenshot.crop(
(left * 1.25, top * 1.25, right * 1.25, bottom * 1.25))
captcha.save(name)
return captcha
# 7.登录按钮获取
def click_button(self):
submit = self.wait.until(EC.element_to_be_clickable(
(By.XPATH,
'//body/div[3]/div[1]/div[3]/div[1]/form[1]/p[4]/input[1]')))
submit.click()
time.sleep(5)
print('登录成功')
# 8.登录
def login(self):
self.input_info()
# 获取验证码图片
image = self.captcha_img()
bytes_arr = BytesIO()
image.save(bytes_arr, format='PNG')
# 识别验证码
result = self.chaojiying.PostPic(bytes_arr.getvalue(), cjy_id)
print(result)
# pic_str是识别出的验证码内容
code = result['pic_str']
inputcode = self.wait.until(EC.presence_of_element_located(
(By.XPATH,
'//body/div[3]/div[1]/div[3]/div[1]/form[1]/p[3]/input[1]')))
inputcode.send_keys(code)
time.sleep(1)
self.click_button()
# 判断是否成功
# 打印当前剩余积分
jifen = self.wait.until(EC.presence_of_element_located((By.XPATH,
'//div[@class="index_box mat8"]/div/span')))
print('当前剩余积分为:', jifen.text)
if __name__ == '__main__':
button = ChaojiyingLogin()
button.login()
运行结果